This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

What does it mean to say "ARM Cortex-M processors are entirey C programmable"?

Hi,

Being new to the fascinating ARM world, I am going through various documentation and reading material.

I read that the ARM Cortex-M processors (or I think it applies to all the Cortex processors) are entirely C programmable. This means that assembly code is not required for start-up code and for ISRs.

I am curious to find out what prohibits the earlier ARM processors (or even other architectures) to write the start-up code in C? Are these any specific instructions? One which I found was the WFI (Wait For Interrupt) which can't have an equivalent in C. But that is not a start-up or ISR instruction.

Thanks for your support !

Gopal

Parents
  • jensbauer wrote:

    (Note: programming in assembly language is also easier on the Cortex-M than on earlier ARM based architectures; especially when speaking about interrupts and context-switching).

    A bit off-topic, but I feel like mentioning the Cortex-A srs/rfe instructions have made things almost as easy on the A-side also, allowing two-stack or even single-stack applications.  I actually have in some project:

    // more or less emulate the simplicity of the Cortex-M series on Cortex-A
    //
    // for handler mode can use:
    //      0b11111  system mode (same stack as thread mode)
    //      0b10011  supervisor mode (separate stack)
    //
    #define MODE_USR 0b10000        // thread-mode, unprivileged
    #define MODE_THR 0b11111        // thread-mode, privileged
    #define MODE_HND 0b11111        // handler-mode (always privileged)
    
    .macro .handler name, lradjust
    .fun \name&
    .if \lradjust&
            sub     lr, \lradjust&  // fix return address
    .endif
            srsfd   sp!, MODE_HND   // save { lr, spsr } to handler stack
            cps     MODE_HND        // change to handler mode
    .endm
    
    .macro hret
            rfefd   sp!             // pop { pc, cpsr }
    .endm
    

    and then for example

    .handler irq_handler, 4
            push    { r0-r3, r12, lr }
    
            // ... interrupt dispatching code here ...
    
            pop     { r0-r3, r12, lr }
            hret
    

    handling syscalls is in some sense easier than on cortex-M:  don't save/restore r0-r3, just save/restore lr (not needed if two stacks are used and syscalls are only made from "thread mode"), and for example dispatch to the appropriate handler based on r12. Register arguments and return value get passed through transparently.

Reply
  • jensbauer wrote:

    (Note: programming in assembly language is also easier on the Cortex-M than on earlier ARM based architectures; especially when speaking about interrupts and context-switching).

    A bit off-topic, but I feel like mentioning the Cortex-A srs/rfe instructions have made things almost as easy on the A-side also, allowing two-stack or even single-stack applications.  I actually have in some project:

    // more or less emulate the simplicity of the Cortex-M series on Cortex-A
    //
    // for handler mode can use:
    //      0b11111  system mode (same stack as thread mode)
    //      0b10011  supervisor mode (separate stack)
    //
    #define MODE_USR 0b10000        // thread-mode, unprivileged
    #define MODE_THR 0b11111        // thread-mode, privileged
    #define MODE_HND 0b11111        // handler-mode (always privileged)
    
    .macro .handler name, lradjust
    .fun \name&
    .if \lradjust&
            sub     lr, \lradjust&  // fix return address
    .endif
            srsfd   sp!, MODE_HND   // save { lr, spsr } to handler stack
            cps     MODE_HND        // change to handler mode
    .endm
    
    .macro hret
            rfefd   sp!             // pop { pc, cpsr }
    .endm
    

    and then for example

    .handler irq_handler, 4
            push    { r0-r3, r12, lr }
    
            // ... interrupt dispatching code here ...
    
            pop     { r0-r3, r12, lr }
            hret
    

    handling syscalls is in some sense easier than on cortex-M:  don't save/restore r0-r3, just save/restore lr (not needed if two stacks are used and syscalls are only made from "thread mode"), and for example dispatch to the appropriate handler based on r12. Register arguments and return value get passed through transparently.

Children
No data