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

Cortex-M0(+) support #1

Closed
japaric opened this issue Mar 12, 2017 · 1 comment
Closed

Cortex-M0(+) support #1

japaric opened this issue Mar 12, 2017 · 1 comment

Comments

@japaric
Copy link
Collaborator

japaric commented Mar 12, 2017

There's no BASEPRI on this architecture.

We can start with just supporting cooperative tasks and then support lock by manually masking the other tasks using NVIC.

@japaric
Copy link
Collaborator Author

japaric commented Jul 29, 2017

Fixed in #34

All Cortex-M devices have the same level of support now.

@japaric japaric closed this as completed Jul 29, 2017
japaric added a commit that referenced this issue Nov 9, 2017
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
bors bot pushed a commit that referenced this issue Jul 20, 2021
japaric pushed a commit that referenced this issue Sep 10, 2021
andrewgazelka pushed a commit to andrewgazelka/cortex-m-rtic that referenced this issue Nov 3, 2021
make the reset handler private
andrewgazelka pushed a commit to andrewgazelka/cortex-m-rtic that referenced this issue Nov 3, 2021
When I currently request GDB to dump a hard fault stack, I see
something like this:
    (gdb) bt
    #0  UserHardFault_ (ef=0x10001fb8) at /depots/cortex-m-rt/src/lib.rs:537
    rtic-rs#1  0x08003fe6 in HardFault ()
    Backtrace stopped: previous frame identical to this frame (corrupt stack?)

GDB can't unwind past HardFault since the current implementation of
this function overwrites the Link Register (LR) value. This change
pushes LR and R0 (to maintain 8-byte stack alignment) to the stack
before transferring execution to UserHardFault().

After this change, I see a callstack like this from GDB:
    (gdb) bt
    #0  UserHardFault_ (ef=0x10001fb0) at /depots/cortex-m-rt/src/lib.rs:537
    rtic-rs#1  0x08003fe8 in HardFault ()
    rtic-rs#2  <signal handler called>
    rtic-rs#3  0x08002820 in core::ptr::read_volatile (src=0x48001800) at libcore/ptr.rs:472
    rtic-rs#4  0x080001a2 in main () at src/07-registers/src/main.rs:14

Notes:
* This code uses 8 more stack bytes.
* Increases the size of the HardFault handler by 2 narrow instructions
  or 4 bytes. This could be decreased to 2 bytes by removing the pop
  since UserHardFault() doesn't currently return but it just looks too
  odd for me to do as an initial attempt.
andrewgazelka pushed a commit to andrewgazelka/cortex-m-rtic that referenced this issue Nov 3, 2021
131: Allow GDB to unwind HardFault callstacks r=therealprof a=adamgreen

When I currently request GDB to dump a hard fault stack, I see
something like this:
```
(gdb) bt
#0  UserHardFault_ (ef=0x10001fb8) at /depots/cortex-m-rt/src/lib.rs:537
rtic-rs#1  0x08003fe6 in HardFault ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
```
GDB can't unwind past HardFault since the current implementation of
this function overwrites the Link Register (LR) value. This change
pushes LR and R0 (to maintain 8-byte stack alignment) to the stack
before transferring execution to UserHardFault().

After this change, I see a callstack like this from GDB:
```
(gdb) bt
#0  UserHardFault_ (ef=0x10001fb0) at /depots/cortex-m-rt/src/lib.rs:537
rtic-rs#1  0x08003fe8 in HardFault ()
rtic-rs#2  <signal handler called>
rtic-rs#3  0x08002820 in core::ptr::read_volatile (src=0x48001800) at libcore/ptr.rs:472
rtic-rs#4  0x080001a2 in main () at src/07-registers/src/main.rs:14
```
Notes:
* This code uses 8 more stack bytes.
* Increases the size of the HardFault handler by 2 narrow instructions
  or 4 bytes. This could be decreased to 2 bytes by removing the pop
  since UserHardFault() doesn't currently return but it just looks too
  odd for me to do as an initial attempt.

Co-authored-by: Adam Green <adamgreen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant