rbkettlewell / max32660-hal

HAL for the MAX32660 microcontroller.
BSD Zero Clause License
0 stars 0 forks source link

Investigate mocking interface for Kora board #3

Open ryanorendorff opened 2 years ago

ryanorendorff commented 2 years ago

We could potentially set up the GPIO macros/etc to work on traits instead of functions. This would allow us to switch out the backend while keeping the business logic the same.

Mainly this could be used for behavioral testing, not cycle accurate testing.

So the million dollar question: is behavioral testing in the HAL (and letting users have access to that type of testing) useful?

Below is an example of how such an idea could potentially work in Rust. Note that the copy trait is a red herring to enable the pin variable to be used more than once. Maybe this could be altered to a mutable reference instead to be able to reference the object multiple times.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bf4c36c4cb159697a500e510d794ea54

use core::marker::PhantomData;
​
trait PinMethods {
    fn set(&mut self,  value: u32);
    fn read(&self) -> u32;
}
​
​
#[derive(Clone, Copy)]
struct RealPin {
    state: PhantomData<u32>
}
​
#[derive(Clone, Copy)]
struct FakePin {
    state: u32
}
​
impl PinMethods for RealPin {
    fn set(&mut self, _value: u32) {
        // Pretend to actual set the value of the register
    }
​
    fn read(&self) -> u32 {
        // pretend to read in the value of the pin 
        0
    }
}
​
impl PinMethods for FakePin {
    fn set(&mut self, value: u32) {
        println!("Setting with value {}", value);
        self.state = value;
    }
​
    fn read(&self) -> u32 {
        println!("Reading a value {}", self.state);
        self.state
    }
}
​
fn test_program<T: PinMethods + Copy>(mut pin: T) -> u32 {
    pin.set(12);
    pin.read()
}
​
fn main() {
    println!("Hello, world!");
​
    // To be able to run the program on an actual ARM processor (MAX32660)
    println!("Running with real pins");
    test_program(RealPin {state: PhantomData});
​
    // To be able to test the program behavior without the device
    println!("Running with fake pins");
    test_program(FakePin {state: 0});
}