aboutsummaryrefslogtreecommitdiff
path: root/examples/one-task.rs
blob: 8cfe089c08d2537a480a64f80c855d59ffcdb90b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! An application with one task

#![deny(unsafe_code)]
#![feature(const_fn)]
#![feature(proc_macro)]
#![no_std]

extern crate cortex_m;
#[macro_use(task)]
extern crate cortex_m_rtfm as rtfm;
extern crate stm32f103xx;

use cortex_m::peripheral::SystClkSource;
use rtfm::{app, Threshold};

app! {
    device: stm32f103xx,

    // Here tasks are declared
    //
    // Each task corresponds to an interrupt or an exception. Every time the
    // interrupt or exception becomes *pending* the corresponding task handler
    // will be executed.
    tasks: {
        // Here we declare that we'll use the SYS_TICK exception as a task
        SYS_TICK: {
            // This is the priority of the task.
            // 1 is the lowest priority a task can have.
            // The maximum priority is determined by the number of priority bits
            // the device has. This device has 4 priority bits so 16 is the
            // maximum value.
            priority: 1,

            // These are the *resources* associated with this task
            //
            // The peripherals that the task needs can be listed here
            resources: [GPIOC],
        },
    }
}

fn init(p: init::Peripherals) {
    // power on GPIOC
    p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());

    // configure PC13 as output
    p.GPIOC.bsrr.write(|w| w.bs13().set());
    p.GPIOC
        .crh
        .modify(|_, w| w.mode13().output().cnf13().push());

    // configure the system timer to generate one interrupt every second
    p.SYST.set_clock_source(SystClkSource::Core);
    p.SYST.set_reload(8_000_000); // 1s
    p.SYST.enable_interrupt();
    p.SYST.enable_counter();
}

fn idle() -> ! {
    loop {
        rtfm::wfi();
    }
}

// This binds the `sys_tick` handler to the `SYS_TICK` task
//
// This particular handler has local state associated to it. The value of the
// `STATE` variable will be preserved across invocations of this handler
task!(SYS_TICK, sys_tick, Locals {
    static STATE: bool = false;
});

// This is the task handler of the SYS_TICK exception
//
// `t` is the preemption threshold token. We won't use it this time.
// `l` is the data local to this task. The type here must match the one declared
// in `task!`.
// `r` is the resources this task has access to. `SYS_TICK::Resources` has one
// field per resource declared in `app!`.
fn sys_tick(_t: &mut Threshold, l: &mut Locals, r: SYS_TICK::Resources) {
    // toggle state
    *l.STATE = !*l.STATE;

    if *l.STATE {
        // set the pin PC13 high
        r.GPIOC.bsrr.write(|w| w.bs13().set());
    } else {
        // set the pin PC13 low
        r.GPIOC.bsrr.write(|w| w.br13().reset());
    }
}