Hi everybody,
I want to use the the RTC (Real Time Counter) interrupt in my code. To do it, I need to program the associated RTC_IRQHandler function which is declared in the startup-ARMC0plus.s file.
;/**************************************************************************//** ; * @file startup_ARMCM0plus.s ; * @brief CMSIS Core Device Startup File for ; * ARMCM0plus Device Series ; * @author S.Wright ; * @version v1.1.0 ; * @date 2018/06/19 ; * @attention changes from original startup_ARMCM0plus.s are copyright: 2016..2018, Cobham AES ; * ; * @note ; * ; ******************************************************************************/ ;/* Copyright (c) 2012 ARM LIMITED ; ; All rights reserved. ; Redistribution and use in source and binary forms, with or without ; modification, are permitted provided that the following conditions are met: ; - Redistributions of source code must retain the above copyright ; notice, this list of conditions and the following disclaimer. ; - Redistributions in binary form must reproduce the above copyright ; notice, this list of conditions and the following disclaimer in the ; documentation and/or other materials provided with the distribution. ; - Neither the name of ARM nor the names of its contributors may be used ; to endorse or promote products derived from this software without ; specific prior written permission. ; * ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE ; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ; POSSIBILITY OF SUCH DAMAGE. ; ---------------------------------------------------------------------------*/ ;/* ;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------ ;*/ ; <h> Stack Configuration ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> ; Stack_Size EQU 0x00000400 #### TEST ONLY -- S.Wright, 2017/10/12 Stack_Size EQU 0x00000800 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp ; <h> Heap Configuration ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> ; Heap_Size EQU 0x00000C00 Heap_Size EQU 0x00001000 ; #### TEST ONLY -- S.Wright, 2017/07/06 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit PRESERVE8 THUMB ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors ; Reset SP/vector DCD __initial_sp ; -16: Top of Stack DCD Reset_Handler ; -15: Reset Handler ; Internal Interrupts DCD NMI_Handler ; -14: NMI Handler DCD HardFault_Handler ; -13: Hard Fault Handler DCD 0 ; -12: reserved DCD 0 ; -11: reserved DCD 0 ; -10: reserved DCD 0 ; -9: reserved DCD 0 ; -8: reserved DCD 0 ; -7: reserved DCD 0 ; -6: reserved DCD SVC_Handler ; -5: SVCall Handler DCD 0 ; -4: reserved DCD 0 ; -3: reserved DCD PendSV_Handler ; -2: PendSV Handler DCD SysTick_Handler ; -1: SysTick Handler ; External Interrupts: UT32M0R500-specific DCD MBEA_IRQHandler ; 0: MBEA DCD DUALTIMER0_IRQHandler ; 1: DualTimer0 DCD DUALTIMER1_IRQHandler ; 2: DualTimer1 DCD PWM_IRQHandler ; 3: PWM DCD RTC_IRQHandler ; 4: RTC DCD GPIO0_16_IRQHandler ; 5: GPIO16 [GPIO1, Pin 0] DCD GPIO0_17_IRQHandler ; 6: GPIO17 [GPIO1, Pin 1] DCD GPIO0_18_IRQHandler ; 7: GPIO18 [GPIO1, Pin 2] DCD GPIO0_19_IRQHandler ; 8: GPIO19 [GPIO1, Pin 3] DCD GPIO0_20_IRQHandler ; 9: GPIO20 [GPIO1, Pin 4] DCD GPIO0_21_IRQHandler ; 10: GPIO21 [GPIO1, Pin 5] DCD GPIO0_22_IRQHandler ; 11: GPIO22 [GPIO1, Pin 6] DCD GPIO0_23_IRQHandler ; 12: GPIO23 [GPIO1, Pin 7] DCD Default_Handler ; 13: reserved DCD UART0_IRQHandler ; 14: UART0 DCD UART1_IRQHandler ; 15: UART1 DCD CAN0_IRQHandler ; 16: CAN0 DCD CAN1_IRQHandler ; 17: CAN1 DCD I2C0_IRQHandler ; 18: I2C0 DCD I2C1_IRQHandler ; 19: I2C1 DCD SPI_IRQHandler ; 20: SPI DCD ADC_IRQHandler ; 21: ADC DCD GPIO0_ALL_IRQHandler ; 22: GPIO0 combined DCD GPIO1_ALL_IRQHandler ; 23: GPIO1 combined DCD GPIO2_ALL_IRQHandler ; 24: GPIO2 combined DCD Default_Handler ; 25: reserved DCD Default_Handler ; 26: reserved DCD Default_Handler ; 27: reserved DCD Default_Handler ; 28: reserved DCD Default_Handler ; 29: reserved DCD Default_Handler ; 30: reserved DCD Default_Handler ; 31: reserved __Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors AREA |.text|, CODE, READONLY ; Reset Handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP ; Dummy Exception Handlers (infinite loops which can be modified) NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDP SVC_Handler PROC EXPORT SVC_Handler [WEAK] B . ENDP PendSV_Handler PROC EXPORT PendSV_Handler [WEAK] B . ENDP SysTick_Handler PROC EXPORT SysTick_Handler [WEAK] B . ENDP Default_Handler PROC EXPORT MBEA_IRQHandler [WEAK] EXPORT DUALTIMER0_IRQHandler [WEAK] EXPORT DUALTIMER1_IRQHandler [WEAK] EXPORT PWM_IRQHandler [WEAK] EXPORT RTC_IRQHandler [WEAK] EXPORT GPIO0_16_IRQHandler [WEAK] EXPORT GPIO0_17_IRQHandler [WEAK] EXPORT GPIO0_18_IRQHandler [WEAK] EXPORT GPIO0_19_IRQHandler [WEAK] EXPORT GPIO0_20_IRQHandler [WEAK] EXPORT GPIO0_21_IRQHandler [WEAK] EXPORT GPIO0_22_IRQHandler [WEAK] EXPORT GPIO0_23_IRQHandler [WEAK] EXPORT UART0_IRQHandler [WEAK] EXPORT UART1_IRQHandler [WEAK] EXPORT CAN0_IRQHandler [WEAK] EXPORT CAN1_IRQHandler [WEAK] EXPORT I2C0_IRQHandler [WEAK] EXPORT I2C1_IRQHandler [WEAK] EXPORT SPI_IRQHandler [WEAK] EXPORT ADC_IRQHandler [WEAK] EXPORT GPIO0_ALL_IRQHandler [WEAK] EXPORT GPIO1_ALL_IRQHandler [WEAK] EXPORT GPIO2_ALL_IRQHandler [WEAK] MBEA_IRQHandler DUALTIMER0_IRQHandler DUALTIMER1_IRQHandler PWM_IRQHandler RTC_IRQHandler GPIO0_16_IRQHandler GPIO0_17_IRQHandler GPIO0_18_IRQHandler GPIO0_19_IRQHandler GPIO0_20_IRQHandler GPIO0_21_IRQHandler GPIO0_22_IRQHandler GPIO0_23_IRQHandler UART0_IRQHandler UART1_IRQHandler CAN0_IRQHandler CAN1_IRQHandler I2C0_IRQHandler I2C1_IRQHandler SPI_IRQHandler ADC_IRQHandler GPIO0_ALL_IRQHandler GPIO1_ALL_IRQHandler GPIO2_ALL_IRQHandler B . ENDP ALIGN ; User Initial Stack & Heap IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap PROC LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ENDP ALIGN ENDIF END
First, I initialized the RTC in a counter.c file as follow. It wrap when it reaches 0x1FFFFFFF and the interruption must be risen.
#define C_RTC_PLACE_BIT_3 3 #define C_RTC_PLACE_BIT_2 2 #define C_RTC_PLACE_BIT_1 1 #define C_RTC_PLACE_BIT_0 0 #define C_INIT_RTC_WEN 1 // RTC wrap enable #define C_INIT_RTC_EN 1 // Start RTC #define C_INIT_RTC_MASK 0 // no mask on interrupts #define C_INIT_RTC_IEN 1 // interrupts enable #define C_INIT_COUNTER_CONTROL_MASK ((C_INIT_RTC_WEN<<C_RTC_PLACE_BIT_3) | (C_INIT_RTC_EN<< C_RTC_PLACE_BIT_2) | (C_INIT_RTC_MASK<<C_RTC_PLACE_BIT_1) | (C_INIT_RTC_IEN<<C_RTC_PLACE_BIT_0) ) void counterInit(void) { NVIC_SetPriority (RTC_IRQn, 0); NVIC_EnableIRQ(RTC_IRQn); s_counter->counterMatchRegister = 0x1FFFFFFF; s_counter->counterControlRegister = C_INIT_COUNTER_CONTROL_MASK; }
I also programmed the RTC_IRQHandler in the same file
void RTC_IRQHandler(void); void RTC_IRQHandler(void) { volatile t_int32u l_readEOIRegister; s_extraBitsCounter++; // increment a counter l_readEOIRegister = s_counter->endOfInterruptRegister; // read EOI register to clear it NVIC_ClearPendingIRQ(RTC_IRQn); }
However, when the counter wraps, the interrupts is risen but the program never enter the RTC_IRQHandler function.
What could be wrong ?
Thank you for your help.
Best regards.
Rémi G.
Are you sure that your implementation of the IRQ handler is being included in the build? Check your .map file. If the address of the RTC handler is the same as all the other defaults, your impl has not been included. I have seen this issue before, with the Keil IDE I think.
My function is defined in the image symbol two times :
As follow in the Local Symbols
i.RTC_IRQHandler 0x20000384 Section 0 counter.o(i.RTC_IRQHandler)
and as follow in Global Symbols
RTC_IRQHandler 0x20000385 Thumb Code 34 counter.o(i.RTC_IRQHandler)
Finally it is defined in the Memory Map of the image as follow
0x20000384 0x20000384 0x00000030 Code RO 234 i.RTC_IRQHandler counter.o
What could be the error ?
Maybe the PRIMASK register is blocking interrupts.
Thank you for your help but according to keil, the PRIMASK is desactivated.
And keil do something strange. When I run the program, everything runs correctly (except the interrupt). When I stop it, and re run it, it is stuck in this assembly line. When I run step by step, this problem never occurs.
0x0000022A E7FE B 0x0000022A
Can the issues have a link ?
Best regards
This is a long shot, but thought it might help. I noticed that your RTC handler is at address 20000384. I work on CM3, your system appears to be a CM0plus? I think that on both systems, flash is at 0 and ram starts at 20000000. If correct, your handler might be being placed in RAM. Do you have anything like __ramfunc in your code, or perhaps your handler is marked as going in a .ram section.
If your entire vector table is somehow being put into ram too, you'll have to re-locate your VTOR. If not, perhaps ram-located funcs cannot be in the vector table? Could the branch distance be too large, and you might need 'veneers', handled by the linker?
I just think your 20000384 address is a bit suspicious, as the address of an ISR that is.
the 20th vector table entry holds the address that will be called when an RTC_IRQ happens
Make sure address 0x00000050 has 0x20000384, If it has 0x0000022A, it is not using your routine but the default routine (which is branch to 0x0000022A)
It is is 0x20000384, you need to check which interrupt is actually active at this point.
Thank you for all the answers.
I didn't defined the System Control Space (SCS) and so the System Control Block (SCB) and the NVIC.
Finally, I declared the Interrupt Vector at the right SRAM adress... and It works ! (see core_cm0plus.h)