Browse Source

Enforce better safety guarentees

* Makes use of Rcc parameters rather than making RCC pointers
* Applys CS parameters to GPIO functions that mutate the port non
atomically
* Cut down on build gating hell a bit
trying.tmp
HarkonenBade 4 years ago
parent
commit
7ea2af8a74
  1. 1
      CHANGELOG.md
  2. 49
      examples/adc_values.rs
  3. 33
      examples/blinky.rs
  4. 41
      examples/blinky_adc.rs
  5. 27
      examples/blinky_delay.rs
  6. 59
      examples/blinky_multiple.rs
  7. 25
      examples/blinky_timer.rs
  8. 38
      examples/flash_systick.rs
  9. 66
      examples/led_hal_button_irq.rs
  10. 25
      examples/serial_echo.rs
  11. 41
      examples/serial_spi_bridge.rs
  12. 61
      examples/spi_hal_apa102c.rs
  13. 53
      examples/watchdog.rs
  14. 69
      src/adc.rs
  15. 14
      src/delay.rs
  16. 78
      src/gpio.rs
  17. 23
      src/i2c.rs
  18. 11
      src/lib.rs
  19. 75
      src/rcc.rs
  20. 55
      src/serial.rs
  21. 67
      src/spi.rs
  22. 50
      src/timers.rs
  23. 6
      src/watchdog.rs

1
CHANGELOG.md

@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Changed
- Optimize delay implemenation (#42) - @david-sawatzke
- Enforced more rigorous safety guarentees (#41 - Very breaking change) - @HarkonenBade
### Fixed

49
examples/adc_values.rs

@ -29,40 +29,41 @@ fn main() -> ! {
hal::stm32::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
let gpioa = p.GPIOA.split();
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
let mut syst = cp.SYST;
let gpioa = p.GPIOA.split(&mut rcc);
// Set source for SysTick counter, here full operating frequency (== 8MHz)
syst.set_clock_source(Core);
let mut syst = cp.SYST;
// Set reload value, i.e. timer delay 8 MHz/counts
syst.set_reload(8_000_000 - 1);
// Set source for SysTick counter, here full operating frequency (== 8MHz)
syst.set_clock_source(Core);
// Start SysTick counter
syst.enable_counter();
// Set reload value, i.e. timer delay 8 MHz/counts
syst.set_reload(8_000_000 - 1);
// Start SysTick interrupt generation
syst.enable_interrupt();
// Start SysTick counter
syst.enable_counter();
// USART1 at PA9 (TX) and PA10(RX)
let tx = gpioa.pa9.into_alternate_af1();
let rx = gpioa.pa10.into_alternate_af1();
// Start SysTick interrupt generation
syst.enable_interrupt();
// Initialiase UART
let (mut tx, _) =
hal::serial::Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks).split();
// USART1 at PA9 (TX) and PA10(RX)
let tx = gpioa.pa9.into_alternate_af1(cs);
let rx = gpioa.pa10.into_alternate_af1(cs);
// Initialise ADC
let adc = hal::adc::Adc::new(p.ADC);
// Initialiase UART
let (mut tx, _) =
hal::serial::Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc).split();
// Output a friendly greeting
tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok();
// Initialise ADC
let adc = hal::adc::Adc::new(p.ADC, &mut rcc);
// Move all components under Mutex supervision
cortex_m::interrupt::free(move |cs| {
// Output a friendly greeting
tx.write_str("\n\rThis ADC example will read various values using the ADC and print them out to the serial terminal\r\n").ok();
// Move all components under Mutex supervision
*SHARED.borrow(cs).borrow_mut() = Some(Shared { adc, tx });
});
}

33
examples/blinky.rs

@ -14,21 +14,26 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let Some(p) = stm32::Peripherals::take() {
let gpioa = p.GPIOA.split();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
loop {
/* Turn PA1 on a million times in a row */
for _ in 0..1_000_000 {
led.set_high();
}
/* Then turn PA1 off a million times in a row */
for _ in 0..1_000_000 {
led.set_low();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
let gpioa = p.GPIOA.split(&mut rcc);
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output(cs);
loop {
/* Turn PA1 on a million times in a row */
for _ in 0..1_000_000 {
led.set_high();
}
/* Then turn PA1 off a million times in a row */
for _ in 0..1_000_000 {
led.set_low();
}
}
}
});
}
loop {

41
examples/blinky_adc.rs

@ -18,36 +18,35 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
let gpioa = p.GPIOA.split(&mut rcc);
/* (Re-)configure PA0 as analog in */
let mut an_in = gpioa.pa0.into_analog();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output(cs);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
/* (Re-)configure PA0 as analog in */
let mut an_in = gpioa.pa0.into_analog(cs);
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, &rcc);
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
let mut adc = Adc::new(p.ADC, &mut rcc);
let mut adc = Adc::new(p.ADC);
loop {
led.toggle();
loop {
led.toggle();
let val: u16 = adc.read(&mut an_in).unwrap();
let val: u16 = adc.read(&mut an_in).unwrap();
/* shift the value right by 3, same as divide by 8, reduces
the 0-4095 range into something approximating 1-512 */
let time: u16 = (val >> 3) + 1;
/* shift the value right by 3, same as divide by 8, reduces
the 0-4095 range into something approximating 1-512 */
let time: u16 = (val >> 3) + 1;
delay.delay_ms(time);
}
delay.delay_ms(time);
}
});
}
loop {

27
examples/blinky_delay.rs

@ -16,24 +16,23 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
let gpioa = p.GPIOA.split(&mut rcc);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output(cs);
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, &rcc);
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
loop {
led.toggle();
delay.delay_ms(1_000_u16);
}
loop {
led.toggle();
delay.delay_ms(1_000_u16);
}
});
}
loop {

59
examples/blinky_multiple.rs

@ -16,37 +16,36 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let gpiob = p.GPIOB.split();
/* (Re-)configure PA1 as output */
let led1 = gpioa.pa1.into_push_pull_output();
/* (Re-)configure PB1 as output */
let led2 = gpiob.pb1.into_push_pull_output();
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, clocks);
/* Store them together */
let mut leds = [led1.downgrade(), led2.downgrade()];
loop {
for l in &mut leds {
l.set_high();
}
delay.delay_ms(1_000_u16);
for l in &mut leds {
l.set_low();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.split(&mut rcc);
/* (Re-)configure PA1 as output */
let led1 = gpioa.pa1.into_push_pull_output(cs);
/* (Re-)configure PB1 as output */
let led2 = gpiob.pb1.into_push_pull_output(cs);
/* Get delay provider */
let mut delay = Delay::new(cp.SYST, &rcc);
/* Store them together */
let mut leds = [led1.downgrade(), led2.downgrade()];
loop {
for l in &mut leds {
l.set_high();
}
delay.delay_ms(1_000_u16);
for l in &mut leds {
l.set_low();
}
delay.delay_ms(1_000_u16);
}
delay.delay_ms(1_000_u16);
}
});
}
loop {

25
examples/blinky_timer.rs

@ -17,22 +17,21 @@ use nb::block;
#[entry]
fn main() -> ! {
if let Some(p) = stm32::Peripherals::take() {
let gpioa = p.GPIOA.split();
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
/* Constrain clocking registers */
let rcc = p.RCC.constrain();
let gpioa = p.GPIOA.split(&mut rcc);
/* (Re-)configure PA1 as output */
let mut led = gpioa.pa1.into_push_pull_output(cs);
/* Configure clock to 8 MHz (i.e. the default) and freeze it */
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc);
let mut timer = Timer::tim1(p.TIM1, Hertz(1), clocks);
loop {
led.toggle();
block!(timer.wait()).ok();
}
loop {
led.toggle();
block!(timer.wait()).ok();
}
});
}
loop {

38
examples/flash_systick.rs

@ -23,32 +23,34 @@ static GPIO: Mutex<RefCell<Option<gpioa::PA1<Output<PushPull>>>>> = Mutex::new(R
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let rcc = p.RCC.constrain();
let _ = rcc.cfgr.sysclk(48.mhz()).freeze();
let mut syst = cp.SYST;
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash);
/* (Re-)configure PA1 as output */
let led = gpioa.pa1.into_push_pull_output();
let gpioa = p.GPIOA.split(&mut rcc);
let mut syst = cp.SYST;
/* (Re-)configure PA1 as output */
let led = gpioa.pa1.into_push_pull_output(cs);
cortex_m::interrupt::free(move |cs| {
*GPIO.borrow(cs).borrow_mut() = Some(led);
});
/* Initialise SysTick counter with a defined value */
unsafe { syst.cvr.write(1) };
/* Initialise SysTick counter with a defined value */
unsafe { syst.cvr.write(1) };
/* Set source for SysTick counter, here full operating frequency (== 8MHz) */
syst.set_clock_source(Core);
/* Set source for SysTick counter, here full operating frequency (== 8MHz) */
syst.set_clock_source(Core);
/* Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms */
syst.set_reload(4_000_000 - 1);
/* Set reload value, i.e. timer delay 48 MHz/4 Mcounts == 12Hz or 83ms */
syst.set_reload(4_000_000 - 1);
/* Start counter */
syst.enable_counter();
/* Start counter */
syst.enable_counter();
/* Start interrupt generation */
syst.enable_interrupt();
/* Start interrupt generation */
syst.enable_interrupt();
});
}
loop {

66
examples/led_hal_button_irq.rs

@ -31,53 +31,53 @@ static INT: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (Peripherals::take(), c_m_Peripherals::take()) {
let gpioa = p.GPIOA.split();
let gpiob = p.GPIOB.split();
let syscfg = p.SYSCFG_COMP;
let exti = p.EXTI;
cortex_m::interrupt::free(move |cs| {
// Enable clock for SYSCFG
let rcc = p.RCC;
rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit());
// Enable clock for SYSCFG
let rcc = p.RCC;
rcc.apb2enr.modify(|_, w| w.syscfgen().set_bit());
let mut flash = p.FLASH;
let mut rcc = rcc.configure().sysclk(8.mhz()).freeze(&mut flash);
// Configure PB1 as input (button)
let _ = gpiob.pb1.into_pull_down_input();
let gpioa = p.GPIOA.split(&mut rcc);
let gpiob = p.GPIOB.split(&mut rcc);
let syscfg = p.SYSCFG_COMP;
let exti = p.EXTI;
// Configure PA1 as output (LED)
let mut led = gpioa.pa1.into_push_pull_output();
// Configure PB1 as input (button)
let _ = gpiob.pb1.into_pull_down_input(cs);
// Turn off LED
led.set_low();
// Configure PA1 as output (LED)
let mut led = gpioa.pa1.into_push_pull_output(cs);
// Configure clock to 8 MHz (i.e. the default) and freeze it
let clocks = rcc.constrain().cfgr.sysclk(8.mhz()).freeze();
// Turn off LED
led.set_low();
// Initialise delay provider
let delay = Delay::new(cp.SYST, clocks);
// Initialise delay provider
let delay = Delay::new(cp.SYST, &rcc);
// Enable external interrupt for PB1
syscfg
.syscfg_exticr1
.modify(|_, w| unsafe { w.exti1().bits(1) });
// Enable external interrupt for PB1
syscfg
.syscfg_exticr1
.modify(|_, w| unsafe { w.exti1().bits(1) });
// Set interrupt request mask for line 1
exti.imr.modify(|_, w| w.mr1().set_bit());
// Set interrupt request mask for line 1
exti.imr.modify(|_, w| w.mr1().set_bit());
// Set interrupt rising trigger for line 1
exti.rtsr.modify(|_, w| w.tr1().set_bit());
// Set interrupt rising trigger for line 1
exti.rtsr.modify(|_, w| w.tr1().set_bit());
// Move control over LED and DELAY and EXTI into global mutexes
cortex_m::interrupt::free(move |cs| {
// Move control over LED and DELAY and EXTI into global mutexes
*LED.borrow(cs).borrow_mut() = Some(led);
*DELAY.borrow(cs).borrow_mut() = Some(delay);
*INT.borrow(cs).borrow_mut() = Some(exti);
});
// Enable EXTI IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
nvic.enable(Interrupt::EXTI0_1);
unsafe { nvic.set_priority(Interrupt::EXTI0_1, 1) };
cortex_m::peripheral::NVIC::unpend(Interrupt::EXTI0_1);
// Enable EXTI IRQ, set prio 1 and clear any pending IRQs
let mut nvic = cp.NVIC;
nvic.enable(Interrupt::EXTI0_1);
unsafe { nvic.set_priority(Interrupt::EXTI0_1, 1) };
cortex_m::peripheral::NVIC::unpend(Interrupt::EXTI0_1);
});
}
loop {

25
examples/serial_echo.rs

@ -17,21 +17,24 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let Some(p) = stm32::Peripherals::take() {
let gpioa = p.GPIOA.split();
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.sysclk(48.mhz()).freeze();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(48.mhz()).freeze(&mut flash);
let tx = gpioa.pa9.into_alternate_af1();
let rx = gpioa.pa10.into_alternate_af1();
let gpioa = p.GPIOA.split(&mut rcc);
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks);
let tx = gpioa.pa9.into_alternate_af1(cs);
let rx = gpioa.pa10.into_alternate_af1(cs);
let (mut tx, mut rx) = serial.split();
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc);
loop {
let received = block!(rx.read()).unwrap();
block!(tx.write(received)).ok();
}
let (mut tx, mut rx) = serial.split();
loop {
let received = block!(rx.read()).unwrap();
block!(tx.write(received)).ok();
}
});
}
loop {

41
examples/serial_spi_bridge.rs

@ -30,34 +30,37 @@ fn main() -> ! {
};
if let Some(p) = stm32::Peripherals::take() {
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let gpioa = p.GPIOA.split();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().freeze(&mut flash);
// Configure pins for SPI
let sck = gpioa.pa5.into_alternate_af0();
let miso = gpioa.pa6.into_alternate_af0();
let mosi = gpioa.pa7.into_alternate_af0();
let gpioa = p.GPIOA.split(&mut rcc);
// Configure SPI with 1MHz rate
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 1.mhz(), clocks);
// Configure pins for SPI
let sck = gpioa.pa5.into_alternate_af0(cs);
let miso = gpioa.pa6.into_alternate_af0(cs);
let mosi = gpioa.pa7.into_alternate_af0(cs);
let tx = gpioa.pa9.into_alternate_af1();
let rx = gpioa.pa10.into_alternate_af1();
// Configure SPI with 1MHz rate
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 1.mhz(), &mut rcc);
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks);
let tx = gpioa.pa9.into_alternate_af1(cs);
let rx = gpioa.pa10.into_alternate_af1(cs);
let (mut tx, mut rx) = serial.split();
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc);
loop {
let serial_received = block!(rx.read()).unwrap();
let (mut tx, mut rx) = serial.split();
block!(spi.send(serial_received)).ok();
loop {
let serial_received = block!(rx.read()).unwrap();
let spi_received = block!(spi.read()).unwrap();
block!(spi.send(serial_received)).ok();
block!(tx.write(spi_received)).ok();
}
let spi_received = block!(spi.read()).unwrap();
block!(tx.write(spi_received)).ok();
}
});
}
loop {

61
examples/spi_hal_apa102c.rs

@ -21,42 +21,45 @@ fn main() -> ! {
};
if let Some(p) = stm32::Peripherals::take() {
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let gpioa = p.GPIOA.split();
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().freeze(&mut flash);
// Configure pins for SPI
let sck = gpioa.pa5.into_alternate_af0();
let miso = gpioa.pa6.into_alternate_af0();
let mosi = gpioa.pa7.into_alternate_af0();
let gpioa = p.GPIOA.split(&mut rcc);
// Configure SPI with 100kHz rate
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000.hz(), clocks);
// Configure pins for SPI
let sck = gpioa.pa5.into_alternate_af0(cs);
let miso = gpioa.pa6.into_alternate_af0(cs);
let mosi = gpioa.pa7.into_alternate_af0(cs);
// Cycle through colors on 16 chained APA102C LEDs
loop {
for r in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, 0, r]);
// Configure SPI with 100kHz rate
let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), MODE, 100_000.hz(), &mut rcc);
// Cycle through colors on 16 chained APA102C LEDs
loop {
for r in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, 0, r]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
for b in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, b, 0, 0]);
for b in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, b, 0, 0]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
for g in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, g, 0]);
for g in 0..255 {
let _ = spi.write(&[0, 0, 0, 0]);
for _i in 0..16 {
let _ = spi.write(&[0b1110_0001, 0, g, 0]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
let _ = spi.write(&[0xFF, 0xFF, 0xFF, 0xFF]);
}
}
});
}
loop {

53
examples/watchdog.rs

@ -20,39 +20,42 @@ use cortex_m_rt::entry;
#[entry]
fn main() -> ! {
if let (Some(p), Some(cp)) = (stm32::Peripherals::take(), Peripherals::take()) {
let gpioa = p.GPIOA.split();
let rcc = p.RCC.constrain();
let dbgmcu = p.DBGMCU;
cortex_m::interrupt::free(move |cs| {
let mut flash = p.FLASH;
let mut rcc = p.RCC.configure().sysclk(8.mhz()).freeze(&mut flash);
// Disable the watchdog when the cpu is stopped under debug
dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit());
let gpioa = p.GPIOA.split(&mut rcc);
let dbgmcu = p.DBGMCU;
let mut watchdog = Watchdog::new(p.IWDG);
let clocks = rcc.cfgr.sysclk(8.mhz()).freeze();
// Disable the watchdog when the cpu is stopped under debug
dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit());
// Get delay provider
let mut delay = Delay::new(cp.SYST, clocks);
let mut watchdog = Watchdog::new(p.IWDG);
let tx = gpioa.pa9.into_alternate_af1();
let rx = gpioa.pa10.into_alternate_af1();
// Get delay provider
let mut delay = Delay::new(cp.SYST, &rcc);
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), clocks);
let tx = gpioa.pa9.into_alternate_af1(cs);
let rx = gpioa.pa10.into_alternate_af1(cs);
let (mut tx, _rx) = serial.split();
tx.write_str("RESET \r\n").ok();
let serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc);
watchdog.start(Hertz(1));
delay.delay_ms(500_u16);
watchdog.feed();
delay.delay_ms(500_u16);
watchdog.feed();
delay.delay_ms(500_u16);
tx.write_str("This will get printed \r\n").ok();
watchdog.feed();
let (mut tx, _rx) = serial.split();
tx.write_str("RESET \r\n").ok();
// Now a reset happens while delaying
delay.delay_ms(1500_u16);
tx.write_str("This won't\r\n").ok();
watchdog.start(Hertz(1));
delay.delay_ms(500_u16);
watchdog.feed();
delay.delay_ms(500_u16);
watchdog.feed();
delay.delay_ms(500_u16);
tx.write_str("This will get printed \r\n").ok();
watchdog.feed();
// Now a reset happens while delaying
delay.delay_ms(1500_u16);
tx.write_str("This won't\r\n").ok();
});
}
loop {

69
src/adc.rs

@ -12,52 +12,45 @@
//! use crate::hal::prelude::*;
//! use crate::hal::adc::Adc;
//!
//! let mut p = stm32::Peripherals::take().unwrap();
//! cortex_m::interrupt::free(|cs| {
//! let mut p = stm32::Peripherals::take().unwrap();
//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH);
//!
//! let mut led = gpioa.pa1.into_push_pull_pull_output();
//! let mut an_in = gpioa.pa0.into_analog();
//! let gpioa = p.GPIOA.split(&mut rcc);
//!
//! let rcc = p.RCC.constrain().cfgr.freeze();
//! let mut delay = Delay::new(cp.SYST, clocks);
//! let mut led = gpioa.pa1.into_push_pull_pull_output(cs);
//! let mut an_in = gpioa.pa0.into_analog(cs);
//!
//! let mut adc = Adc::new(p.ADC);
//! let mut delay = Delay::new(cp.SYST, &rcc);
//!
//! loop {
//! let val: u16 = adc.read(&mut an_in).unwrap();
//! if val < ((1 << 8) - 1) {
//! led.set_low();
//! } else {
//! led.set_high();
//! let mut adc = Adc::new(p.ADC, &mut rcc);
//!
//! loop {
//! let val: u16 = adc.read(&mut an_in).unwrap();
//! if val < ((1 << 8) - 1) {
//! led.set_low();
//! } else {
//! led.set_high();
//! }
//! delay.delay_ms(50_u16);
//! }
//! delay.delay_ms(50_u16);
//! }
//! });
//! ```
#[cfg(feature = "device-selected")]
const VREFCAL: *const u16 = 0x1FFF_F7BA as *const u16;
#[cfg(feature = "device-selected")]
const VTEMPCAL30: *const u16 = 0x1FFF_F7B8 as *const u16;
#[cfg(feature = "device-selected")]
const VTEMPCAL110: *const u16 = 0x1FFF_F7C2 as *const u16;
#[cfg(feature = "device-selected")]
const VDD_CALIB: u16 = 3300;
#[cfg(feature = "device-selected")]
use core::ptr;
#[cfg(feature = "device-selected")]
use embedded_hal::{
adc::{Channel, OneShot},
blocking::delay::DelayUs,
};
#[cfg(feature = "device-selected")]
use crate::{delay::Delay, gpio::*, stm32};
use crate::{delay::Delay, gpio::*, rcc::Rcc, stm32};
#[cfg(feature = "device-selected")]
/// Analog to Digital converter interface
pub struct Adc {
rb: stm32::ADC,
@ -89,7 +82,6 @@ pub enum AdcSampleTime {
T_239,
}
#[cfg(feature = "device-selected")]
impl AdcSampleTime {
fn write_bits(self, adc: &mut stm32::ADC) {
unsafe {
@ -137,7 +129,6 @@ pub enum AdcAlign {
LeftAsRM,
}
#[cfg(feature = "device-selected")]
impl AdcAlign {
fn write_bits(self, adc: &mut stm32::ADC) {
adc.cfgr1.write(|w| {
@ -168,7 +159,6 @@ pub enum AdcPrecision {
B_6,
}
#[cfg(feature = "device-selected")]
impl AdcPrecision {
fn write_bits(self, adc: &mut stm32::ADC) {
unsafe {
@ -189,7 +179,6 @@ impl AdcPrecision {
}
}
#[cfg(feature = "device-selected")]
macro_rules! adc_pins {
($($pin:ty => $chan:expr),+ $(,)*) => {
$(
@ -202,7 +191,6 @@ macro_rules! adc_pins {
};
}
#[cfg(feature = "device-selected")]
adc_pins!(
gpioa::PA0<Analog> => 0_u8,
gpioa::PA1<Analog> => 1_u8,
@ -239,13 +227,11 @@ pub struct VTemp;
/// Internal voltage reference (ADC Channel 17)
pub struct VRef;
#[cfg(feature = "device-selected")]
adc_pins!(
VTemp => 16_u8,
VRef => 17_u8,
);
#[cfg(feature = "device-selected")]
impl VTemp {
/// Init a new VTemp
pub fn new() -> Self {
@ -319,7 +305,6 @@ impl VTemp {
}
}
#[cfg(feature = "device-selected")]
impl VRef {
/// Init a new VRef
pub fn new() -> Self {
@ -421,21 +406,20 @@ impl VBat {
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StoredConfig(AdcSampleTime, AdcAlign, AdcPrecision);
#[cfg(feature = "device-selected")]
impl Adc {
/// Init a new Adc
///
/// Sets all configurable parameters to defaults, enables the HSI14 clock
/// for the ADC if it is not already enabled and performs a boot time
/// calibration. As such this method may take an appreciable time to run.
pub fn new(adc: stm32::ADC) -> Self {
pub fn new(adc: stm32::ADC, rcc: &mut Rcc) -> Self {
let mut s = Self {
rb: adc,
sample_time: AdcSampleTime::default(),
align: AdcAlign::default(),
precision: AdcPrecision::default(),
};
s.select_clock();
s.select_clock(rcc);
s.calibrate();
s
}
@ -527,12 +511,10 @@ impl Adc {
while self.rb.cr.read().adcal().bit_is_set() {}
}
fn select_clock(&mut self) {
let rcc = unsafe { &*stm32::RCC::ptr() };
rcc.apb2enr.modify(|_, w| w.adcen().set_bit());
rcc.cr2.write(|w| w.hsi14on().set_bit());
while rcc.cr2.read().hsi14rdy().bit_is_clear() {}
fn select_clock(&mut self, rcc: &mut Rcc) {
rcc.regs.apb2enr.modify(|_, w| w.adcen().set_bit());
rcc.regs.cr2.write(|w| w.hsi14on().set_bit());
while rcc.regs.cr2.read().hsi14rdy().bit_is_clear() {}
}
fn power_up(&mut self) {
@ -569,7 +551,6 @@ impl Adc {
}
}
#[cfg(feature = "device-selected")]
impl<WORD, PIN> OneShot<Adc, WORD, PIN> for Adc
where
WORD: From<u16>,

14
src/delay.rs

@ -18,8 +18,8 @@
//! let mut p = stm32::Peripherals::take().unwrap();
//! let mut cp = cortex_m::Peripherals::take().unwrap();
//!
//! let clocks = p.RCC.constrain().cfgr.freeze();
//! let mut delay = Delay::new(cp.SYST, clocks);
//! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH);
//! let mut delay = Delay::new(cp.SYST, &rcc);
//! loop {
//! delay.delay_ms(1_000_u16);
//! }
@ -29,7 +29,8 @@ use cast::{u16, u32};
use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use crate::rcc::Clocks;
use crate::rcc::Rcc;
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
/// System timer (SysTick) as a delay provider
@ -42,14 +43,15 @@ const SYSTICK_RANGE: u32 = 0x0100_0000;
impl Delay {
/// Configures the system timer (SysTick) as a delay provider
pub fn new(mut syst: SYST, clocks: Clocks) -> Delay {
pub fn new(mut syst: SYST, rcc: &Rcc) -> Delay {
syst.set_clock_source(SystClkSource::Core);
syst.set_reload(SYSTICK_RANGE - 1);
syst.clear_current();
syst.enable_counter();
assert!(clocks.hclk().0 >= 1_000_000);
let scale = clocks.hclk().0 / 1_000_000;
assert!(rcc.clocks.hclk().0 >= 1_000_000);
let scale = rcc.clocks.hclk().0 / 1_000_000;
Delay { scale }
// As access to the count register is possible without a reference to the systick, we can

78
src/gpio.rs

@ -2,13 +2,15 @@
use core::marker::PhantomData;
use crate::rcc::Rcc;
/// Extension trait to split a GPIO peripheral in independent pins and registers
pub trait GpioExt {
/// The parts to split the GPIO into
type Parts;
/// Splits the GPIO block into independent pins and registers
fn split(self) -> Self::Parts;
fn split(self, rcc: &mut Rcc) -> Self::Parts;
}
trait GpioRegExt {
@ -116,7 +118,6 @@ impl<MODE> InputPin for Pin<Input<MODE>> {
}
}
#[allow(unused)]
macro_rules! gpio_trait {
($gpiox:ident) => {
impl GpioRegExt for crate::stm32::$gpiox::RegisterBlock {
@ -143,13 +144,9 @@ macro_rules! gpio_trait {
};
}
#[cfg(feature = "device-selected")]
gpio_trait!(gpioa);
#[cfg(feature = "device-selected")]
gpio_trait!(gpiof);
#[allow(unused)]
macro_rules! gpio {
($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, [
$($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
@ -159,9 +156,13 @@ macro_rules! gpio {
use core::marker::PhantomData;
use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable};
use crate::stm32::$GPIOX;
use crate::{
rcc::Rcc,
stm32::$GPIOX
};
use cortex_m::interrupt::CriticalSection;
use crate::stm32::RCC;
use super::{
Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output,
PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7,
@ -179,10 +180,8 @@ macro_rules! gpio {
impl GpioExt for $GPIOX {
type Parts = Parts;
fn split(self) -> Parts {
// NOTE(unsafe) This executes only during initialisation
let rcc = unsafe { &(*RCC::ptr()) };
rcc.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
fn split(self, rcc: &mut Rcc) -> Parts {
rcc.regs.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
Parts {
$(
@ -201,8 +200,7 @@ macro_rules! gpio {
&(*$GPIOX::ptr()).afrl.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
});
} else
{
} else {
let offset2 = offset2 - 32;
&(*$GPIOX::ptr()).afrh.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
@ -223,7 +221,7 @@ macro_rules! gpio {
impl<MODE> $PXi<MODE> {
/// Configures the pin to operate in AF0 mode
pub fn into_alternate_af0(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF0>> {
_set_alternate_mode($i, 0);
$PXi { _mode: PhantomData }
@ -231,7 +229,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF1 mode
pub fn into_alternate_af1(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF1>> {
_set_alternate_mode($i, 1);
$PXi { _mode: PhantomData }
@ -239,7 +237,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF2 mode
pub fn into_alternate_af2(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF2>> {
_set_alternate_mode($i, 2);
$PXi { _mode: PhantomData }
@ -247,7 +245,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF3 mode
pub fn into_alternate_af3(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF3>> {
_set_alternate_mode($i, 3);
$PXi { _mode: PhantomData }
@ -255,7 +253,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF4 mode
pub fn into_alternate_af4(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF4>> {
_set_alternate_mode($i, 4);
$PXi { _mode: PhantomData }
@ -263,7 +261,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF5 mode
pub fn into_alternate_af5(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF5>> {
_set_alternate_mode($i, 5);
$PXi { _mode: PhantomData }
@ -271,7 +269,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF6 mode
pub fn into_alternate_af6(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF6>> {
_set_alternate_mode($i, 6);
$PXi { _mode: PhantomData }
@ -279,7 +277,7 @@ macro_rules! gpio {
/// Configures the pin to operate in AF7 mode
pub fn into_alternate_af7(
self,
self, _cs: &CriticalSection
) -> $PXi<Alternate<AF7>> {
_set_alternate_mode($i, 7);
$PXi { _mode: PhantomData }
@ -287,7 +285,7 @@ macro_rules! gpio {
/// Configures the pin to operate as a floating input pin
pub fn into_floating_input(
self,
self, _cs: &CriticalSection
) -> $PXi<Input<Floating>> {
let offset = 2 * $i;
unsafe {
@ -303,7 +301,7 @@ macro_rules! gpio {
/// Configures the pin to operate as a pulled down input pin
pub fn into_pull_down_input(
self,
self, _cs: &CriticalSection
) -> $PXi<Input<PullDown>> {
let offset = 2 * $i;
unsafe {
@ -319,7 +317,7 @@ macro_rules! gpio {
/// Configures the pin to operate as a pulled up input pin
pub fn into_pull_up_input(
self,
self, _cs: &CriticalSection
) -> $PXi<Input<PullUp>> {
let offset = 2 * $i;
unsafe {
@ -335,7 +333,7 @@ macro_rules! gpio {
/// Configures the pin to operate as an analog pin
pub fn into_analog(
self,
self, _cs: &CriticalSection
) -> $PXi<Analog> {
let offset = 2 * $i;
unsafe {
@ -351,7 +349,7 @@ macro_rules! gpio {
/// Configures the pin to operate as an open drain output pin
pub fn into_open_drain_output(
self,
self, _cs: &CriticalSection
) -> $PXi<Output<OpenDrain>> {
let offset = 2 * $i;
unsafe {
@ -370,10 +368,9 @@ macro_rules! gpio {
/// Configures the pin to operate as an push pull output pin
pub fn into_push_pull_output(
self,
self, _cs: &CriticalSection
) -> $PXi<Output<PushPull>> {
let offset = 2 * $i;
unsafe {
&(*$GPIOX::ptr()).pupdr.modify(|r, w| {
w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
@ -391,10 +388,9 @@ macro_rules! gpio {
/// Configures the pin to operate as an push pull output pin with quick fall
/// and rise times
pub fn into_push_pull_output_hs(
self,
self, _cs: &CriticalSection
) -> $PXi<Output<PushPull>> {
let offset = 2 * $i;
unsafe {
&(*$GPIOX::ptr()).pupdr.modify(|r, w| {
w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))