Hi, I was trying to use timer interrupt in LPC54628J512ET180. I used __NVIC_SetVector(CTIMER0_IRQn, (uint32_t)ctimer0_ISR); to set the address for the function that will handler Ctimer0 interrupt. however the moment I enable the interrupt(using __NVIC_EnableIRQ(CTIMER0_IRQn);) the code go to HardFault_handler();.
So the issue is with __NVIC_SetVector() . I think the issue with relocating VTOR to SRAM. But I thought Startup file will be doing so. Also, I used SDK to create some of the files in the project(configure the system clock).
Any advise of what should I do. Any help will be appreciated. Thanks again!
Hi @frank_m , Thanks for your respond. I will type my solution, as reference for others.
For me it was not necessarily to try using different interrupt Name.
So I used the provided interrupt Handler Name's function from Startup file.
So here How I tried to implement the timer interrupt.
the Ctimer0_intialize() is called in the main. I was just testing everything out so probably you do not need to do same steps of initialization. and I set random value for timer interrupt.
CTIMER_Type is a struct that hold timer registers. it already exist in LPC54628.h
the timer interrupt handler, I used the same Name in Startup file. and this function is written before the main function. or define its prototype inside a header that is included in the main. all what this interrupt_handler do is toggle an LED ON and off.
If timer interrupt occur and you did not correctly define a handler with the same Name, it goes to the default handler which is HardFault_Handler();
so, the following is from Startup.
if you using sdk and included timer files. these file might already have CTIMER0_DriverIRQHandler() defined there, so be aware of declaring CTIMER0_DriverIRQHandler again without removing it from the already existed file.
I think you did not fully grasp the idea behind the handling of interrupt handler names in most Cortex M toolchains.
As you might know, the core uses a table with a list of all interrupt vectors specified for this specific MCU, starting with the reset vector. All offsets into this table are fixed for a specific MCU, with the first dozen (roughly) fixed for all MCUs (defined by ARM).
Since the MCU starts from the reset handler, it was choosen to define the entire vector table, and initial settings for all entries (or some of them). Often default handlers that do nothing but a while (1) loop. Those functions are defined as WEAK, a method that allows the linker to deal with two symbols of the same name. Actual names depend on the toolchain, and might differ from one to another.
And yes, for using a peripheral and it's interrupts, you are supposed to use exactly the name as defined in the startup file / vector table. And not declaring your function as WEAK gives it precedence over the default function. This happens at link time, no need to change the vector (handler address) at runtime using __NVIC_SetVector().
> if you using sdk and included timer files. these file might already have CTIMER0_DriverIRQHandler() defined there, so be aware of declaring CTIMER0_DriverIRQHandler again without removing it from the already existed file.
This SDK interrupt handler is then already part of your (example) application - as if you had written it.
Since the SDK example sources are copied into the project, I use to overwrite such interrupt handlers if they don't fit my purpose. "Overwrite" meaning remove the provided code, and add your own.
Some frameworks (like RTOSes) "seize" most interrupt handlers, and provide callbacks instead.
Thanks for your replay. I understand what you mean. the interrupt worked with me. and I only Post my solution to clarify it for others. the reason I tried to write my own function at the beginning was because I used to do that with different micro using__attribute__ . I believe your replay would be helping to anyone who will read this thread. thanks again.
The "__attribute__" keyword is typical for gcc-based toolchains.
In the Keil toolchain, the definition looks like this (in assembler):
HardFault_Handler\
PROC
EXPORT HardFault_Handler [WEAK]
In the Segger Embedded Studio (also a gcc-based toolchain) like this, again assember:
.weak HardFault_Handler
.section .init.HardFault_Handler, "ax"
.balign 2
.thumb_func
HardFault_Handler:
Most toolchains come with a decent documentation and tutorial nowadays.
Not sure why you want to change an interrupt handler at runtime. I never tried that, or had the incentive to do so.
But you would need to relocate the vector table to RAM, as the CMSIS documentation states:
https://www.keil.com/pack/doc/CMSIS/Core/html/group__NVIC__gr.html
Have you checked the SCB registers for the cause of the hardfault ?
https://www.keil.com/appnotes/files/apnt209.pdf