aboutsummaryrefslogtreecommitdiff
path: root/examples/cfg-monotonic.rs
blob: 88c0d6f009f9dd5a2065c434b58220f15a084f6e (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! examples/cfg-monotonic.rs

#![deny(unsafe_code)]
#![deny(warnings)]
#![deny(missing_docs)]
#![no_main]
#![no_std]

use panic_semihosting as _;

#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
mod app {
    use cortex_m_semihosting::{debug, hprintln};
    use systick_monotonic::*; // Implements the `Monotonic` trait

    // A monotonic timer to enable scheduling in RTIC
    #[cfg(feature = "killmono")]
    #[monotonic(binds = SysTick, default = true)]
    type MyMono = Systick<100>; // 100 Hz / 10 ms granularity

    // Not allowed by current rtic-syntax:
    // error: `#[monotonic(...)]` on a specific type must appear at most once
    //   --> examples/cfg-monotonic.rs:23:10
    //    |
    // 23 |     type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
    //    |          ^^^^^^
    // #[monotonic(binds = SysTick, default = true)]
    // type MyMono = Systick<100>; // 100 Hz / 10 ms granularity

    // Not allowed by current rtic-syntax:
    // error: this interrupt is already bound
    //   --> examples/cfg-monotonic.rs:31:25
    //    |
    // 31 |     #[monotonic(binds = SysTick, default = true)]
    //    |                         ^^^^^^^
    // #[monotonic(binds = SysTick, default = true)]
    // type MyMono2 = DwtSystick<100>; // 100 Hz / 10 ms granularity

    // Resources shared between tasks
    #[shared]
    struct Shared {
        s1: u32,
        s2: i32,
    }

    // Local resources to specific tasks (cannot be shared)
    #[local]
    struct Local {
        l1: u8,
        l2: i8,
    }

    #[init]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
        let _systick = cx.core.SYST;

        // Initialize the monotonic (SysTick rate in QEMU is 12 MHz)
        #[cfg(feature = "killmono")]
        let mono = Systick::new(systick, 12_000_000);

        // Spawn the task `foo` directly after `init` finishes
        foo::spawn().unwrap();

        debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator

        (
            // Initialization of shared resources
            Shared { s1: 0, s2: 1 },
            // Initialization of task local resources
            Local { l1: 2, l2: 3 },
            // Move the monotonic timer to the RTIC run-time, this enables
            // scheduling
            #[cfg(feature = "killmono")]
            init::Monotonics(mono),
            init::Monotonics(),
        )
    }

    // Background task, runs whenever no other tasks are running
    #[idle]
    fn idle(_: idle::Context) -> ! {
        loop {
            continue;
        }
    }

    // Software task, not bound to a hardware interrupt.
    // This task takes the task local resource `l1`
    // The resources `s1` and `s2` are shared between all other tasks.
    #[task(shared = [s1, s2], local = [l1])]
    fn foo(_: foo::Context) {
        // This task is only spawned once in `init`, hence this task will run
        // only once

        hprintln!("foo");
    }

    // Software task, also not bound to a hardware interrupt
    // This task takes the task local resource `l2`
    // The resources `s1` and `s2` are shared between all other tasks.
    #[task(shared = [s1, s2], local = [l2])]
    fn bar(_: bar::Context) {
        hprintln!("bar");

        // Run `bar` once per second
        // bar::spawn_after(1.secs()).unwrap();
    }

    // Hardware task, bound to a hardware interrupt
    // The resources `s1` and `s2` are shared between all other tasks.
    #[task(binds = UART0, priority = 3, shared = [s1, s2])]
    fn uart0_interrupt(_: uart0_interrupt::Context) {
        // This task is bound to the interrupt `UART0` and will run
        // whenever the interrupt fires

        // Note that RTIC does NOT clear the interrupt flag, this is up to the
        // user

        hprintln!("UART0 interrupt!");
    }
}