aboutsummaryrefslogtreecommitdiff
path: root/macros/src/codegen/spawn_body.rs
blob: 3c2e8a0392522b678cc9e1c2870574c870f0f84f (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
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use rtic_syntax::{ast::App, Context};
use syn::Ident;

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

pub fn codegen(
    spawner: Context,
    name: &Ident,
    app: &App,
    analysis: &Analysis,
    extra: &Extra,
) -> TokenStream2 {
    let spawnee = &app.software_tasks[name];
    let priority = spawnee.args.priority;

    let write_instant = if app.uses_schedule() {
        let instants = util::instants_ident(name);

        Some(quote!(
            #instants.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(instant);
        ))
    } else {
        None
    };

    let t = util::spawn_t_ident(priority);
    let fq = util::fq_ident(name);
    let rq = util::rq_ident(priority);
    let (dequeue, enqueue) = if spawner.is_init() {
        (
            quote!(#fq.dequeue()),
            quote!(#rq.enqueue_unchecked((#t::#name, index));),
        )
    } else {
        (
            quote!((#fq { priority }.lock(|fq| fq.split().1.dequeue()))),
            quote!((#rq { priority }.lock(|rq| {
                rq.split().0.enqueue_unchecked((#t::#name, index))
            }));),
        )
    };

    let device = extra.device;
    let enum_ = util::interrupt_ident();
    let interrupt = &analysis.interrupts.get(&priority);
    let pend = {quote!(
            rtic::pend(#device::#enum_::#interrupt);
        )
    };

    let (_, tupled, _, _) = util::regroup_inputs(&spawnee.inputs);
    let inputs = util::inputs_ident(name);
    quote!(
        unsafe {
            use rtic::Mutex as _;

            let input = #tupled;
            if let Some(index) = #dequeue {
                #inputs.get_unchecked_mut(usize::from(index)).as_mut_ptr().write(input);

                #write_instant

                #enqueue

                #pend

                Ok(())
            } else {
                Err(input)
            }
        }
    )
}