Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update RTFM-based examples #173

Merged
merged 5 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
63 changes: 34 additions & 29 deletions examples/timer-interrupt-rtfm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -22,80 +21,86 @@ 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<Output<PushPull>> = ();
static mut TIMER_HANDLER: CountDownTimer<pac::TIM1> = ();
static mut LED_STATE: bool = false;

#[init]
fn init() -> init::LateResources {
struct Resources {
led: PC13<Output<PushPull>>,
timer_handler: CountDownTimer<pac::TIM1>,

#[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.

// 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();
}
};
38 changes: 21 additions & 17 deletions examples/usb_serial_rtfm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<bus::UsbBusAllocator<UsbBusType>> = 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
Expand All @@ -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,
};
Expand All @@ -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);
}
};

Expand Down