aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen/timer_queue.rs
blob: 896b3a83f6e41ce16855ab6d6c7bed3e3a62a55d (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::ast::App;

use crate::{analyze::Analysis, check::Extra, codegen::util};

/// Generates timer queues and timer queue handlers
pub fn codegen(app: &App, analysis: &Analysis, _extra: &Extra) -> Vec<TokenStream2> {
    let mut items = vec![];

    if !app.monotonics.is_empty() {
        // Generate the marker counter used to track for `cancel` and `reschedule`
        let tq_marker = util::timer_queue_marker_ident();
        items.push(quote!(
            // #[doc = #doc]
            #[doc(hidden)]
            #[allow(non_camel_case_types)]
            #[allow(non_upper_case_globals)]
            static #tq_marker: rtic::RacyCell<u32> = rtic::RacyCell::new(0);
        ));

        let t = util::schedule_t_ident();

        // Enumeration of `schedule`-able tasks
        {
            let variants = app
                .software_tasks
                .iter()
                .map(|(name, task)| {
                    let cfgs = &task.cfgs;

                    quote!(
                        #(#cfgs)*
                        #name
                    )
                })
                .collect::<Vec<_>>();

            // For future use
            // let doc = "Tasks that can be scheduled".to_string();
            items.push(quote!(
                // #[doc = #doc]
                #[doc(hidden)]
                #[allow(non_camel_case_types)]
                #[derive(Clone, Copy)]
                pub enum #t {
                    #(#variants,)*
                }
            ));
        }
    }

    for (_, monotonic) in &app.monotonics {
        let monotonic_name = monotonic.ident.to_string();
        let tq = util::tq_ident(&monotonic_name);
        let t = util::schedule_t_ident();
        let mono_type = &monotonic.ty;
        let m_ident = util::monotonic_ident(&monotonic_name);

        // Static variables and resource proxy
        {
            // For future use
            // let doc = &format!("Timer queue for {}", monotonic_name);
            let cap: usize = app
                .software_tasks
                .iter()
                .map(|(_name, task)| task.args.capacity as usize)
                .sum();
            let n = util::capacity_literal(cap);
            let tq_ty = quote!(rtic::export::TimerQueue<#mono_type, #t, #n>);

            // For future use
            // let doc = format!(" RTIC internal: {}:{}", file!(), line!());
            items.push(quote!(
                #[doc(hidden)]
                #[allow(non_camel_case_types)]
                #[allow(non_upper_case_globals)]
                static #tq: rtic::RacyCell<#tq_ty> =
                    rtic::RacyCell::new(rtic::export::TimerQueue(rtic::export::SortedLinkedList::new_u16()));
            ));

            let mono = util::monotonic_ident(&monotonic_name);
            // For future use
            // let doc = &format!("Storage for {}", monotonic_name);

            items.push(quote!(
                #[doc(hidden)]
                #[allow(non_camel_case_types)]
                #[allow(non_upper_case_globals)]
                static #mono: rtic::RacyCell<Option<#mono_type>> = rtic::RacyCell::new(None);
            ));
        }

        // Timer queue handler
        {
            let enum_ = util::interrupt_ident();
            let rt_err = util::rt_err_ident();

            let arms = app
                .software_tasks
                .iter()
                .map(|(name, task)| {
                    let cfgs = &task.cfgs;
                    let priority = task.args.priority;
                    let rq = util::rq_ident(priority);
                    let rqt = util::spawn_t_ident(priority);

                    // The interrupt that runs the task dispatcher
                    let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0;

                    let pend = {
                        quote!(
                            rtic::pend(#rt_err::#enum_::#interrupt);
                        )
                    };

                    quote!(
                        #(#cfgs)*
                        #t::#name => {
                            rtic::export::interrupt::free(|_| #rq.get_mut_unchecked().split().0.enqueue_unchecked((#rqt::#name, index)));

                            #pend
                        }
                    )
                })
                .collect::<Vec<_>>();

            let bound_interrupt = &monotonic.args.binds;
            let disable_isr = if &*bound_interrupt.to_string() == "SysTick" {
                quote!(core::mem::transmute::<_, rtic::export::SYST>(()).disable_interrupt())
            } else {
                quote!(rtic::export::NVIC::mask(#rt_err::#enum_::#bound_interrupt))
            };

            items.push(quote!(
                #[no_mangle]
                #[allow(non_snake_case)]
                unsafe fn #bound_interrupt() {
                    while let Some((task, index)) = rtic::export::interrupt::free(|_|
                        if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() {
                            #tq.get_mut_unchecked().dequeue(|| #disable_isr, mono)
                        } else {
                            // We can only use the timer queue if `init` has returned, and it
                            // writes the `Some(monotonic)` we are accessing here.
                            core::hint::unreachable_unchecked()
                        })
                    {
                        match task {
                            #(#arms)*
                        }
                    }

                    rtic::export::interrupt::free(|_| if let Some(mono) = #m_ident.get_mut_unchecked().as_mut() {
                        mono.on_interrupt();
                    });
                }
            ));
        }
    }

    items
}
/scripts/stats/stats.csv?h=fix-s-island-fallback&id=04ea9a4aa47d55620eb2fff3d7bae358979fba0f&follow=1'>[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-27[ci] update lockfile (#2668)Gravatar Fred K. Schott 1-80/+80 2022-02-27[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-26[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-25[ci] yarn formatGravatar natemoo-re 1-20/+20 2022-02-25[ci] release (#2666)astro@0.23.2Gravatar github-actions[bot] 32-59/+57 2022-02-25[ci] yarn formatGravatar natemoo-re 2-12/+6 2022-02-25fix astro scoping of "@import" inside of style tags (#2656)Gravatar Fred K. Schott 3-6/+35 2022-02-25[ci] update lockfile (#2659)Gravatar Fred K. Schott 1-20/+20 2022-02-25feat: improve third-party Astro package compatability (#2665)Gravatar Nate Moore 3-6/+100 2022-02-25get new example working during buildGravatar Fred K. Schott 4-16/+21 2022-02-25[ci] yarn formatGravatar FredKSchott 1-7/+6 2022-02-25Add Non-HTML Pages example (#2637)Gravatar Joel Kuzmarski 11-0/+136 2022-02-25[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-24[ci] yarn formatGravatar natemoo-re 2-24/+24 2022-02-24[ci] release (#2641)astro@0.23.1@astrojs/markdown-remark@0.6.2Gravatar github-actions[bot] 38-90/+81 2022-02-24ensure utf8 encoding when serving html (#2654)Gravatar Fred K. Schott 3-4/+9 2022-02-24fix(core): Issue #2625. error with process.env.LANG larger than 5 (#2645)Gravatar Javier Cortés 2-1/+6 2022-02-24[ci] update lockfile (#2646)Gravatar Fred K. Schott 1-130/+124 2022-02-24chore: upgrade compiler (#2653)Gravatar Nate Moore 3-11/+11 2022-02-24[ci] yarn formatGravatar natemoo-re 2-5/+5 2022-02-24Add fine-grained HMR support (#2649)Gravatar Nate Moore 7-36/+37 2022-02-24[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-23Fixed incorrect types and imports (#2630)Gravatar Juan Martín Seery 27-35/+37 2022-02-23Add sass dev dep to blog-multiple-authors example (#2643)Gravatar Joel Kuzmarski 1-1/+2 2022-02-23Fix(component): align starting position in Markdown slot (#2631)Gravatar Shinobu Hayashi 4-6/+61 2022-02-23[ci] yarn formatGravatar matthewp 1-1/+1 2022-02-23Run all smoke tests with the static build (#2609)Gravatar Matthew Phillips 2-26/+32 2022-02-23[ci] collect statsGravatar FredKSchott 1-0/+1 2022-02-22[ci] update lockfile (#2624)Gravatar Fred K. Schott 1-171/+201 2022-02-22Fixed shiki import to work with "type": "module" (#2628)Gravatar Juan Martín Seery 3-5/+13