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
Hi all,
Thank you very much for the replies. Indeed helpful information and sorry for delayed reply. I
If I can summarize this, these are the points why it is easier to code entirely in C for the ARM Cortex-M:
1. CMSIS offers the wrappers.
2. The SP is initialized by hardware on reset.
3. The interrupt subroutines can be written exactly like normal subroutines. The special interrupt handling (eg. clearing the pending bits) can be done using standard write operations.
Some parts of code like for e.g. the SVC handler would still need some assembly code. Some details are here as well - ARM Information Center
And above all, as Joseph says, this is somewhat a Marketing statement!@
I would like to offer my view on this.
I see it as the ARM Cortex-M is one of the only processors / microcontrollers that offer a complete C-interface, exactly because it allows you to write Interrupt Service Routines as normal subroutines. -There is no difference at all.
The special interrupt handling (eg. clearing the pending bits) can be done using standard write operations.
One could say that the Cortex-M brings microcontrollers closer to C, but I would put it this way:The Cortex-M brings C closer to assembly level (eg. as enhancement).
So it's not really a matter of if it's easier to program the Cortex-M in C compared to assembly langugage (that would probably be true for most microcontrollers / microprocessors anyway; unless they have very little program space).
Rather, I would say that it's about making C programming easier on the Cortex-M than it has ever been before.
(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).
One thing I think that the CMSIS library should probably implement, would be __ROL() and __ROR().
I'm going a bit off-topic here: It's annoying that C still does not have a standardized function for this ... How many years is it since C was invented ? -And we had ROL and ROR instructions since before the 80's, but it's still not present in C++, ObjC or ObjC++.
Thank you jensbauer for your additional input. I have edited my earlier post to include your point. Besides, your off-topic point is also valid
Especially since it would have been a lot easier to add it as a primitive than going through the effort of recognizing an expression which implements a rol/ror using other bitwise ops (which is what all decent C compilers do).
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).
jensbauer wrote:
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.