I’ve been learning how to access the registers directly for my Nano 33 BLE (it uses a nRF52840) via some “NordicSnippets” examples here Nordic Examples
I realise that MBED uses HAL, and that in general the exact same code used in Nordic examples won’t always work in a different development environment. For example, I’m successfully using Arduino’s IDE and source files to experiment with and expand upon various GPIOTE and TIMER examples that I’ve found, some of which require altering to work correctly…
For example, please take a look at the following small program Timer Example
You can see that is uses “TIMER0_IRQHandler”. But for this timer example to work correctly via Arduino/MBED, I’ve had to use “TIMER0_IRQHandler_v”. Notice the “_v”, which I’m guessing is to denote that it’s a vector which is enabled via NVIC.
I have two questions as below…
Are there any official MBED examples that show how to access peripheral registers directly? (e.g., like the Nordic timer example above, but written specifically for MBED users)
Is the equivalence of such syntax, i.e., TIMER0_IRQHandler and TIMER0_IRQHandler_v, documented anywhere by MBED? If so, then please kindly point me in the right direction.
The names of the IRQ handlers are just a convention, and you (or the MBED) are totally free to rename
them if you like different ones. They are just symbols. Important is the position of the IRQ handler inside the vector table. You can find that info for each IRQ handler in the related datasheet. The first in table is always the stack pointer. This is followed by 15 IRQ handlers common to all ARM Cortex M3,4,7 micro-controllers. All the other positions are specific for the given MCU. The maximum number is limited to 256, however, not all of them are used (you can see a 0 at those positions). The Timer0 IRQ handler should be at position 24. If you open the related start up file you will find at that position the symbol (function name) TIMER0_IRQHandler_v. All the IRQ handlers in the Vector table are defined as weak functions and the user (or the Mbed system software) is free to override them by defining his/her implementation with the same name.
Are there any official MBED examples that show how to access peripheral registers directly? (e.g., like the Nordic timer example above, but written specifically for MBED users)
I don’t think there are any official MBED examples showing how to access peripheral registers directly. But it doesn’t matter. Based on the vector table given in the MBED start up file it shouldn’t be a big problem.
Is the equivalence of such syntax, i.e., TIMER0_IRQHandler and TIMER0_IRQHandler_v, documented anywhere by MBED? If so, then please kindly point me in the right direction.
I have no idea why MBED, or it’s partner NORDIC, decided to add “_v” to some IRQ handdle’s name.
And I am also afraid that the only place where one can find the names of the affected handlers is the related start up file (see the link above).
I have replied to you, thank you, but after my 3rd edit, the automatic spam filter has temporarily hidden it. the spam bot says it’ll be back soon after it has been reviewed by a human.
Edit… Hi spam bot. Please disregard my last post. I’ve made considerable progress today, and therefore I’ll be posting an update here tomorrow afternoon, and finalising this thread, thank you.
I’m losing confidence that it’ll ever reappear, so I’m restating a shortened version as below…
They are just symbols. Important is the position of the IRQ handler inside the vector table. You can find that info for each IRQ handler in the related datasheet.
Please provide a link to the related “datasheet” that shows the vector table?
The Timer0 IRQ handler should be at position 24. If you open the related start up file you will find at that position the symbol (function name) TIMER0_IRQHandler_v . All the IRQ handlers in the Vector table are defined as weak functions
Yes I confirm that it is indeed at position 24 under “__Vectors:”.
Please provide a link to the related “datasheet” that shows the vector table.
You can find the nRF52840 product specification (datasheet) at
Chapter 6.1.8 “Interrupts” (page 95) says:
A peripheral only occupies one interrupt, and the interrupt number follows the peripheral ID. For example, the peripheral with ID=4 is connected to interrupt number 4 in the nested vectored interrupt controller (NVIC).
According to the info in chapter 6.30.5 “Registers” (page 422) the Base address of TIMER0 is 0x40008000. Hence, its ID = 8. Because the IRQ handler of the peripheral with ID = 0 is located at the position 16 in the vector table (= 1 Stack pointer + 15 Cortex common interrupts) the position of the TIMER0 IRQ handler should be equal to 24 (= 16 + 8) in the vector table.
I’ll mark your 1st answer as the solution, but this one very nicely completes it for me.
For anyone interested in PPM (related to PWM) which uses such timer functionality as discussed in this thread, then here you’ll find two example programs which I have working very nicely… PPM for Nano 33 BLE