Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] safe creation of &'static mut references #49

Closed
wants to merge 1 commit into from
Closed

Commits on Nov 9, 2017

  1. [WIP] safe creation of &'static mut references

    This implements the "rooting" mechanism proposed in #47. However, it implements a `root` constructor
    function instead of list of `roots` values as originally proposed.
    
    In a nutshell:
    
    - There's a new field, `root`, which takes a path to the "root" constructor function.
    - This constructor has signature `fn() -> T`
    - When the `root` field is used the signature of `init` changes to accommodate a `&'static mut T`
      argument at the end. The `T` in that argument type matches the type returned by the "root"
      constructor.
    - The "root"-ed value is stack allocated.
    
    This enables the safe creation of `&'static mut` references. Example below:
    
    ``` rust
    //#![feature(proc_macro)]
    //#![no_std]
    
    extern crate blue_pill;
    extern crate cortex_m_rt;
    extern crate cortex_m_rtfm as rtfm;
    extern crate heapless;
    
    use blue_pill::stm32f103xx;
    use heapless::RingBuffer;
    use heapless::ring_buffer::{Consumer, Producer};
    use rtfm::{app, Threshold};
    use stm32f103xx::Interrupt;
    
    app! {
        device: stm32f103xx,
    
        resources: {
            static CONSUMER: Consumer<'static, u32, [u32; 8]>;
            static PRODUCER: Producer<'static, u32, [u32; 8]>;
        },
    
        root: root,
    
        idle: {
            resources: [CONSUMER],
        },
    
        tasks: {
            EXTI0: {
                path: exti0,
                resources: [PRODUCER],
            },
        }
    }
    
    struct Root {
        rb: RingBuffer<u32, [u32; 8]>,
    }
    
    fn root() -> Root {
        Root {
            rb: RingBuffer::new(),
        }
    }
    
    fn init(_p: init::Peripherals, root: &'static mut Root) -> init::LateResourceValues {
        let (p, c) = root.rb.split();
    
        init::LateResourceValues {
            CONSUMER: c,
            PRODUCER: p,
        }
    }
    
    fn idle(_t: &mut Threshold, r: idle::Resources) -> ! {
        rtfm::set_pending(Interrupt::EXTI0);
    
        loop {
            if r.CONSUMER.dequeue().is_some() {
                rtfm::bkpt();
            } else {
                rtfm::wfi();
            }
        }
    }
    
    fn exti0(_t: &mut Threshold, r: EXTI0::Resources) {
        r.PRODUCER.enqueue(42).ok();
    
        rtfm::bkpt();
    }
    ```
    
    This produces the following machine code:
    
    ``` armasm
    0800019c <EXTI0>:
     800019c:       f240 0000       movw    r0, #0
     80001a0:       f2c2 0000       movt    r0, #8192       ; 0x2000
     80001a4:       6800            ldr     r0, [r0, #0]
     80001a6:       6803            ldr     r3, [r0, #0]
     80001a8:       6842            ldr     r2, [r0, #4]
     80001aa:       1c51            adds    r1, r2, #1
     80001ac:       f001 0107       and.w   r1, r1, #7
     80001b0:       4299            cmp     r1, r3
     80001b2:       d006            beq.n   80001c2 <EXTI0+0x26>
     80001b4:       eb00 0282       add.w   r2, r0, r2, lsl #2
     80001b8:       232a            movs    r3, #42 ; 0x2a
     80001ba:       6093            str     r3, [r2, #8]
     80001bc:       f3bf 8f5f       dmb     sy
     80001c0:       6041            str     r1, [r0, #4]
     80001c2:       be00            bkpt    0x0000
     80001c4:       4770            bx      lr
    
    080001c6 <main>:
     80001c6:       b08a            sub     sp, #40 ; 0x28  ; Root allocation
     80001c8:       f240 1030       movw    r0, #304        ; 0x130
     80001cc:       4669            mov     r1, sp
     80001ce:       22f0            movs    r2, #240        ; 0xf0
     80001d0:       f6c0 0000       movt    r0, #2048       ; 0x800
     80001d4:       7800            ldrb    r0, [r0, #0]
     80001d6:       2000            movs    r0, #0
     80001d8:       e9cd 0000       strd    r0, r0, [sp]
     80001dc:       f240 0000       movw    r0, #0
     80001e0:       f2c2 0000       movt    r0, #8192       ; 0x2000
     80001e4:       b672            cpsid   i
     80001e6:       6001            str     r1, [r0, #0]    ; PRODUCER = ..
     80001e8:       f240 0004       movw    r0, #4
     80001ec:       f2c2 0000       movt    r0, #8192       ; 0x2000
     80001f0:       6001            str     r1, [r0, #0]    ; CONSUMER = ..
     80001f2:       f24e 4106       movw    r1, #58374      ; 0xe406
     80001f6:       f2ce 0100       movt    r1, #57344      ; 0xe000
     80001fa:       700a            strb    r2, [r1, #0]
     80001fc:       f24e 1100       movw    r1, #57600      ; 0xe100
     8000200:       2240            movs    r2, #64 ; 0x40
     8000202:       f2ce 0100       movt    r1, #57344      ; 0xe000
     8000206:       600a            str     r2, [r1, #0]
     8000208:       b662            cpsie   i
     800020a:       f8c1 2100       str.w   r2, [r1, #256]  ; 0x100
     800020e:       e006            b.n     800021e <main+0x58>
     8000210:       f3bf 8f5f       dmb     sy
     8000214:       3201            adds    r2, #1
     8000216:       f002 0207       and.w   r2, r2, #7
     800021a:       600a            str     r2, [r1, #0]
     800021c:       be00            bkpt    0x0000
     800021e:       6801            ldr     r1, [r0, #0]
     8000220:       684b            ldr     r3, [r1, #4]
     8000222:       680a            ldr     r2, [r1, #0]
     8000224:       429a            cmp     r2, r3
     8000226:       d1f3            bne.n   8000210 <main+0x4a>
     8000228:       bf30            wfi
     800022a:       e7f8            b.n     800021e <main+0x58>
    ```
    
    Unresolved questions:
    
    - Is this mechanism memory safe in presence of `panic!` unwinding?
      - If not, can we generate a compile error if `panic = abort` is *not* used?
    - How does this affect the DMA API proposed in rust-embedded/embedded-hal#14
    
    cc @pftbest
    japaric committed Nov 9, 2017
    Configuration menu
    Copy the full SHA
    e925a3e View commit details
    Browse the repository at this point in the history