diff --git a/Cargo.toml b/Cargo.toml index 557f9b8b..b53a8603 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ optional = true panic-halt = "0.2.0" panic-semihosting = "0.5.2" panic-itm = "0.4.1" -cortex-m-rtfm = "0.4.3" +cortex-m-rtfm = "0.5" cortex-m-semihosting = "0.3.3" heapless = "0.4.3" m = "0.1.1" diff --git a/examples/timer-interrupt-rtfm.rs b/examples/timer-interrupt-rtfm.rs index cdfde84d..86f12dca 100644 --- a/examples/timer-interrupt-rtfm.rs +++ b/examples/timer-interrupt-rtfm.rs @@ -11,7 +11,6 @@ // you can put a breakpoint on `rust_begin_unwind` to catch panics use panic_halt as _; -use cortex_m::asm::wfi; use rtfm::app; use stm32f1xx_hal::{ @@ -22,54 +21,60 @@ use stm32f1xx_hal::{ }; use embedded_hal::digital::v2::OutputPin; -#[app(device = stm32f1xx_hal::pac)] +#[app(device = stm32f1xx_hal::pac, peripherals = true)] const APP: () = { - static mut LED: PC13> = (); - static mut TIMER_HANDLER: CountDownTimer = (); - static mut LED_STATE: bool = false; - - #[init] - fn init() -> init::LateResources { + struct Resources { + led: PC13>, + timer_handler: CountDownTimer, + + #[init(false)] + led_state: bool, + } + #[init] + fn init(cx: init::Context) -> init::LateResources { // Take ownership over the raw flash and rcc devices and convert them into the corresponding // HAL structs - let mut flash = device.FLASH.constrain(); - let mut rcc = device.RCC.constrain(); + let mut flash = cx.device.FLASH.constrain(); + let mut rcc = cx.device.RCC.constrain(); // Freeze the configuration of all the clocks in the system and store the frozen frequencies // in `clocks` let clocks = rcc.cfgr.freeze(&mut flash.acr); // Acquire the GPIOC peripheral - let mut gpioc = device.GPIOC.split(&mut rcc.apb2); + let mut gpioc = cx.device.GPIOC.split(&mut rcc.apb2); // Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the // function in order to configure the port. For pins 0-7, crl should be passed instead let led = gpioc.pc13.into_push_pull_output_with_state(&mut gpioc.crh, State::High); // Configure the syst timer to trigger an update every second and enables interrupt - let mut timer = Timer::tim1(device.TIM1, &clocks, &mut rcc.apb2) + let mut timer = Timer::tim1(cx.device.TIM1, &clocks, &mut rcc.apb2) .start_count_down(1.hz()); timer.listen(Event::Update); // Init the static resources to use them later through RTFM init::LateResources { - LED: led, - TIMER_HANDLER: timer, + led, + timer_handler: timer, } } + // Optional. + // + // https://rtfm.rs/0.5/book/en/by-example/app.html#idle + // > When no idle function is declared, the runtime sets the SLEEPONEXIT bit and then + // > sends the microcontroller to sleep after running init. #[idle] - fn idle() -> ! { - + fn idle(_cx: idle::Context) -> ! { loop { - // Waits for interrupt - wfi(); + cortex_m::asm::wfi(); } } - #[interrupt(priority = 1, resources = [LED, TIMER_HANDLER, LED_STATE])] - fn TIM1_UP() { + #[task(binds = TIM1_UP, priority = 1, resources = [led, timer_handler, led_state])] + fn tick(cx: tick::Context) { // Depending on the application, you could want to delegate some of the work done here to // the idle task if you want to minimize the latency of interrupts with same priority (if // you have any). That could be done with some kind of machine state, etc. @@ -77,25 +82,25 @@ const APP: () = { // Count used to change the timer update frequency static mut COUNT: u8 = 0; - if *resources.LED_STATE { - // Uses resourcers managed by rtfm to turn led off (on bluepill) - resources.LED.set_high().unwrap(); - *resources.LED_STATE = false; + if *cx.resources.led_state { + // Uses resources managed by rtfm to turn led off (on bluepill) + cx.resources.led.set_high().unwrap(); + *cx.resources.led_state = false; } else { - resources.LED.set_low().unwrap(); - *resources.LED_STATE = true; + cx.resources.led.set_low().unwrap(); + *cx.resources.led_state = true; } *COUNT += 1; if *COUNT == 4 { // Changes timer update frequency - resources.TIMER_HANDLER.start(2.hz()); + cx.resources.timer_handler.start(2.hz()); } else if *COUNT == 12 { - resources.TIMER_HANDLER.start(1.hz()); + cx.resources.timer_handler.start(1.hz()); *COUNT = 0; } // Clears the update flag - resources.TIMER_HANDLER.clear_update_interrupt_flag(); + cx.resources.timer_handler.clear_update_interrupt_flag(); } }; diff --git a/examples/usb_serial_rtfm.rs b/examples/usb_serial_rtfm.rs index 527310c2..62e36f72 100644 --- a/examples/usb_serial_rtfm.rs +++ b/examples/usb_serial_rtfm.rs @@ -15,17 +15,19 @@ use usb_device::bus; use usb_device::prelude::*; use usbd_serial::{SerialPort, USB_CLASS_CDC}; -#[app(device = stm32f1xx_hal::stm32)] +#[app(device = stm32f1xx_hal::stm32, peripherals = true)] const APP: () = { - static mut USB_DEV: UsbDevice<'static, UsbBusType> = (); - static mut SERIAL: SerialPort<'static, UsbBusType> = (); + struct Resources { + usb_dev: UsbDevice<'static, UsbBusType>, + serial: SerialPort<'static, UsbBusType>, + } #[init] - fn init() { + fn init(cx: init::Context) -> init::LateResources { static mut USB_BUS: Option> = None; - let mut flash = device.FLASH.constrain(); - let mut rcc = device.RCC.constrain(); + let mut flash = cx.device.FLASH.constrain(); + let mut rcc = cx.device.RCC.constrain(); let clocks = rcc .cfgr @@ -36,21 +38,21 @@ const APP: () = { assert!(clocks.usbclk_valid()); - let mut gpioa = device.GPIOA.split(&mut rcc.apb2); + let mut gpioa = cx.device.GPIOA.split(&mut rcc.apb2); // BluePill board has a pull-up resistor on the D+ line. // Pull the D+ pin down to send a RESET condition to the USB bus. // This forced reset is needed only for development, without it host // will not reset your device when you upload new firmware. let mut usb_dp = gpioa.pa12.into_push_pull_output(&mut gpioa.crh); - usb_dp.set_low(); + usb_dp.set_low().unwrap(); delay(clocks.sysclk().0 / 100); let usb_dm = gpioa.pa11; let usb_dp = usb_dp.into_floating_input(&mut gpioa.crh); let usb = Peripheral { - usb: device.USB, + usb: cx.device.USB, pin_dm: usb_dm, pin_dp: usb_dp, }; @@ -66,18 +68,20 @@ const APP: () = { .device_class(USB_CLASS_CDC) .build(); - USB_DEV = usb_dev; - SERIAL = serial; + init::LateResources { + usb_dev, + serial, + } } - #[interrupt(resources = [USB_DEV, SERIAL])] - fn USB_HP_CAN_TX() { - usb_poll(&mut resources.USB_DEV, &mut resources.SERIAL); + #[task(binds = USB_HP_CAN_TX, resources = [usb_dev, serial])] + fn usb_tx(mut cx: usb_tx::Context) { + usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial); } - #[interrupt(resources = [USB_DEV, SERIAL])] - fn USB_LP_CAN_RX0() { - usb_poll(&mut resources.USB_DEV, &mut resources.SERIAL); + #[task(binds = USB_LP_CAN_RX0, resources = [usb_dev, serial])] + fn usb_rx0(mut cx: usb_rx0::Context) { + usb_poll(&mut cx.resources.usb_dev, &mut cx.resources.serial); } };