6个版本

0.2.1 2020年3月2日
0.2.0 2020年3月2日
0.1.3 2020年1月14日
0.1.2 2019年11月21日

#1761嵌入式开发

每月33次下载

MIT/Apache

22KB
133

Cortex-M中断移动

这是移动到中断上下文的最佳选择。

示例

请查看app-examples文件夹中的完整示例。

目标

这里的目的是替换可能需要整个临界区的互斥锁的使用,而是将数据“移动”到中断上下文中。

这意味着我们不需要临界区来访问它,只需要我们处于移动数据的那个中断中。

这是如何工作的

#![no_std]
#![no_main]

// Panic provider crate
use panic_halt as _;

// CMIM items
use cmim::{
    Move,
    Context,
    Exception,
};

// Used to set the program entry point
use cortex_m_rt::{entry, exception};

use embedded_hal::timer::Cancel;

// Provides definitions for our development board
use dwm1001::{
    cortex_m::peripheral::syst::SystClkSource::Core,
    nrf52832_hal::{
        nrf52832_pac::{interrupt, Interrupt, TIMER1, UARTE0},
        prelude::*,
        Timer, Uarte,
    },
    DWM1001,
};

static TIMER_1_DATA: Move<Timer1Data, Interrupt> = Move::new_uninitialized(Context::Interrupt(Interrupt::TIMER1));
static SYSTICK_DATA: Move<SysTickData, Interrupt> = Move::new_uninitialized(Context::Exception(Exception::SysTick));

struct Timer1Data {
    uart: Uarte<UARTE0>,
    timer: Timer<TIMER1>,
    led: dwm1001::Led,
    toggle: bool,
}

struct SysTickData {
    led: dwm1001::Led,
    toggle: bool,
}

#[entry]
fn main() -> ! {
    if let Some(mut board) = DWM1001::take() {
        let mut timer = board.TIMER0.constrain();
        let mut _rng = board.RNG.constrain();

        let mut itimer = board.TIMER1.constrain();
        itimer.start(1_000_000u32);
        itimer.enable_interrupt(&mut board.NVIC);

        // Core clock is 64MHz, blink at 16Hz
        board.SYST.set_clock_source(Core);
        board.SYST.set_reload(4_000_000 - 1);
        board.SYST.enable_counter();
        board.SYST.enable_interrupt();

        TIMER_1_DATA
            .try_move(Timer1Data {
                uart: board.uart,
                timer: itimer,
                led: board.leds.D9,
                toggle: false,
            })
            .ok();

        SYSTICK_DATA
            .try_move(SysTickData {
                led: board.leds.D12,
                toggle: false,
            })
            .ok();

        let mut toggle = false;

        loop {
            // board.leds.D9  - Top LED GREEN
            // board.leds.D12 - Top LED RED
            // board.leds.D11 - Bottom LED RED
            // board.leds.D10 - Bottom LED BLUE
            if toggle {
                board.leds.D10.enable();
            } else {
                board.leds.D10.disable();
            }

            toggle = !toggle;

            timer.delay(250_000);
        }
    }

    loop {
        continue;
    }
}

#[exception]
fn SysTick() {
    SYSTICK_DATA
        .try_lock(|data| {
            // Blink the LED
            if data.toggle {
                data.led.enable();
            } else {
                data.led.disable();
            }

            data.toggle = !data.toggle;
        })
        .ok();
}

#[interrupt]
fn TIMER1() {
    TIMER_1_DATA
        .try_lock(|data| {
            // Start the timer again first for accuracy
            data.timer.cancel().unwrap();
            data.timer.start(1_000_000u32);

            // Write message to UART. The NRF UART requires data
            // to be in RAM, not flash.
            const MSG_BYTES: &[u8] = "Blink!\r\n".as_bytes();
            let mut buf = [0u8; MSG_BYTES.len()];
            buf.copy_from_slice(MSG_BYTES);

            data.uart.write(&buf).unwrap();

            // Blink the LED
            if data.toggle {
                data.led.enable();
            } else {
                data.led.disable();
            }

            data.toggle = !data.toggle;
        })
        .ok();
}

许可证

以下任一许可证下授权:

任选其一。

贡献

除非你明确声明,否则根据Apache-2.0许可证定义的,你提交给作品以供包含的任何贡献将如上所述双许可,不附加任何额外条款或条件。

依赖项

~1MB
~12K SLoC