Cortex-M0+ core micro Issue with FreeRTOS integration

Hello Team,

I am working on S32K116 micro which is Cortex M0+ core. After Integration of FreeRTOS(V10.3.1), I have modified the handlers to call the functions in startup_S32K116.s file as below.

        PUBWEAK SVC_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
SVC_Handler
        B vPortSVCHandler
	
        PUBWEAK PendSV_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
PendSV_Handler
        B xPortPendSVHandler

        PUBWEAK SysTick_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
SysTick_Handler
        B xPortSysTickHandler

During the compilation process, I got linker error (LP002: relocation failed: value out of range or illegal) for the function “xPortSysTickHandler”.

Then I saw FreeRTOS FAQs and added below macro in the “FreeRTOSConfig.h” file.

#define xPortSysTickHandler     SysTick_Handler

Now I am able to compile and link the files. But while debugging the code with a deugger, I have observed that after a reset, control is not going to reset handler and thus main functio is not executing. It is going to “prvIdleTask()” function after reset. Please suggest if I am missing any thing in the code. Also, please explain why I am geting the linker error before I have added the #define macro.

Regards,
Shashidhar

Can you please post the file that contains your vector table definition as the way you are branching does not look correct - you should just have the address you are branching to installed directly. That is also what is causing your linker error - you are trying to use a branch in instruction that has a maximum range (that is, it only has a fixed number of bits for the branch offset) and the address you are branching to is outside of that range.

Thank you for the reply.
Below is the startup_S32K116.s file.

        MODULE  ?cstartup

        ;; Forward declaration of sections.
        SECTION CSTACK:DATA:NOROOT(3)

        SECTION .intvec:CODE:ROOT(2)

        EXTERN  main
        EXTERN  SystemInit
        EXTERN  init_data_bss
        PUBLIC  __vector_table
        PUBLIC  __vector_table_0x1c
        PUBLIC  __Vectors
        PUBLIC  __Vectors_End
        PUBLIC  __Vectors_Size

        DATA

__vector_table
        DCD   sfe(CSTACK)
        DCD   Reset_Handler                         ; Reset Handler
        DCD   NMI_Handler                        ; Non Maskable Interrupt
        DCD   HardFault_Handler                  ; Cortex-M0 SV Hard Fault Interrupt
        DCD   0
        DCD   0
        DCD   0
__vector_table_0x1c
        DCD   0
        DCD   0
        DCD   0
        DCD   0
        DCD   SVC_Handler                        ; Cortex-M0 SV Call Interrupt
        DCD   0
        DCD   0
        DCD   PendSV_Handler                     ; Cortex-M0 Pend SV Interrupt
        DCD   SysTick_Handler                    ; Cortex-M0 System Tick Interrupt


        DCD   DMA0_IRQHandler                       ; DMA channel 0 transfer complete
        DCD   DMA1_IRQHandler                       ; DMA channel 1 transfer complete
        DCD   DMA2_IRQHandler                       ; DMA channel 2 transfer complete
        DCD   DMA3_IRQHandler                       ; DMA channel 3 transfer complete
        DCD   DMA_Error_IRQHandler                  ; DMA error interrupt channels 0-3
        DCD   ERM_fault_IRQHandler                  ; ERM single and double bit error correction
        DCD   RTC_IRQHandler                        ; RTC alarm interrupt
        DCD   RTC_Seconds_IRQHandler                ; RTC seconds interrupt
        DCD   LPTMR0_IRQHandler                     ; LPTIMER interrupt request
        DCD   PORT_IRQHandler                       ; Port A, B, C, D and E pin detect interrupt
        DCD   CAN0_ORed_Err_Wakeup_IRQHandler       ; OR’ed [Bus Off OR Bus Off Done OR Transmit Warning OR Receive Warning], Interrupt indicating that errors were detected on the CAN bus, Interrupt asserted when Pretended Networking operation is enabled, and a valid message matches the selected filter criteria during Low Power mode
        DCD   CAN0_ORed_0_31_MB_IRQHandler          ; OR’ed Message buffer (0-15, 16-31)
        DCD   FTM0_Ch0_7_IRQHandler                 ; FTM0 Channel 0 to 7 interrupt
        DCD   FTM0_Fault_IRQHandler                 ; FTM0 Fault interrupt
        DCD   FTM0_Ovf_Reload_IRQHandler            ; FTM0 Counter overflow and Reload interrupt
        DCD   FTM1_Ch0_7_IRQHandler                 ; FTM1 Channel 0 to 7 interrupt
        DCD   FTM1_Fault_IRQHandler                 ; FTM1 Fault interrupt
        DCD   FTM1_Ovf_Reload_IRQHandler            ; FTM1 Counter overflow and Reload interrupt
        DCD   FTFC_IRQHandler                       ; FTFC Command complete, Read collision and Double bit fault detect
        DCD   PDB0_IRQHandler                       ; PDB0 interrupt
        DCD   LPIT0_IRQHandler                      ; LPIT interrupt
        DCD   SCG_CMU_LVD_LVWSCG_IRQHandler         ; PMC Low voltage detect interrupt, SCG bus interrupt request and CMU loss of range interrupt
        DCD   WDOG_IRQHandler                       ; WDOG interrupt request out before wdg reset out
        DCD   RCM_IRQHandler                        ; RCM Asynchronous Interrupt
        DCD   LPI2C0_Master_Slave_IRQHandler        ; LPI2C0 Master Interrupt and Slave Interrupt
        DCD   FLEXIO_IRQHandler                     ; FlexIO Interrupt
        DCD   LPSPI0_IRQHandler                     ; LPSPI0 Interrupt
        DCD   Reserved27_IRQHandler                 ; Reserved
        DCD   ADC0_IRQHandler                       ; ADC0 interrupt request.
        DCD   CMP0_IRQHandler                       ; CMP0 interrupt request
        DCD   LPUART1_RxTx_IRQHandler               ; LPUART1 Transmit / Receive  Interrupt
        DCD   LPUART0_RxTx_IRQHandler               ; LPUART0 Transmit / Receive Interrupt
__Vectors_End

        SECTION FlashConfig:CODE
__FlashConfig
        DCD 0xFFFFFFFF    ; 8 bytes backdoor comparison key
        DCD 0xFFFFFFFF    ;
        DCD 0xFFFFFFFF    ; 4 bytes program flash protection bytes
      	DCD 0xFFFF7BFE    ; FDPROT:FEPROT:FOPT:FSEC(0xFE = unsecured)
__FlashConfig_End

__Vectors       EQU   __vector_table
__Vectors_Size  EQU   __Vectors_End - __Vectors


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Default interrupt handlers.
;;
        THUMB

        PUBWEAK Reset_Handler

        EXTERN  vPortSVCHandler
        EXTERN  xPortPendSVHandler
        EXTERN  xPortSysTickHandler

        EXTERN  m_stack_start
        EXTERN  m_stack_end

        SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
        CPSID   I               ; Mask interrupts
        ;; Init the rest of the registers
        LDR     R1,=0
        LDR     R2,=0
        LDR     R3,=0
        LDR     R4,=0
        LDR     R5,=0
        LDR     R6,=0
        LDR     R7,=0
        MOV     R8,R7
        MOV     R9,R7
        MOV     R10,R7
        MOV     R11,R7
        MOV     R12,R7

        ;; Initialize the stack pointer
        LDR     R0, =sfe(CSTACK)
        MOV     R13,R0

#ifndef __NO_SYSTEM_INIT
        ;; Call the CMSIS system init routine
        LDR     R0, =SystemInit
        BLX     R0
#endif

        ;; Init .data and .bss sections
        LDR     R0, =init_data_bss
        BLX     R0
        CPSIE   I               ; Unmask interrupts

        BL      main
JumpToSelf
        B   JumpToSelf

        PUBWEAK NMI_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
NMI_Handler
        B .

        PUBWEAK HardFault_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
HardFault_Handler
        B .


        PUBWEAK SVC_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
SVC_Handler
        B vPortSVCHandler
	
        PUBWEAK PendSV_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
PendSV_Handler
        B xPortPendSVHandler

        PUBWEAK SysTick_Handler
        SECTION .text:CODE:REORDER:NOROOT(1)
SysTick_Handler
        B xPortSysTickHandler

        PUBWEAK    DMA0_IRQHandler
        PUBWEAK    DMA1_IRQHandler
        PUBWEAK    DMA2_IRQHandler
        PUBWEAK    DMA3_IRQHandler
        PUBWEAK    DMA_Error_IRQHandler
        PUBWEAK    ERM_fault_IRQHandler
        PUBWEAK    RTC_IRQHandler
        PUBWEAK    RTC_Seconds_IRQHandler
        PUBWEAK    LPTMR0_IRQHandler
        PUBWEAK    PORT_IRQHandler
        PUBWEAK    CAN0_ORed_Err_Wakeup_IRQHandler
        PUBWEAK    CAN0_ORed_0_31_MB_IRQHandler
        PUBWEAK    FTM0_Ch0_7_IRQHandler
        PUBWEAK    FTM0_Fault_IRQHandler
        PUBWEAK    FTM0_Ovf_Reload_IRQHandler
        PUBWEAK    FTM1_Ch0_7_IRQHandler
        PUBWEAK    FTM1_Fault_IRQHandler
        PUBWEAK    FTM1_Ovf_Reload_IRQHandler
        PUBWEAK    FTFC_IRQHandler
        PUBWEAK    PDB0_IRQHandler
        PUBWEAK    LPIT0_IRQHandler
        PUBWEAK    SCG_CMU_LVD_LVWSCG_IRQHandler
        PUBWEAK    WDOG_IRQHandler
        PUBWEAK    RCM_IRQHandler
        PUBWEAK    LPI2C0_Master_Slave_IRQHandler
        PUBWEAK    FLEXIO_IRQHandler
        PUBWEAK    LPSPI0_IRQHandler
        PUBWEAK    Reserved27_IRQHandler
        PUBWEAK    ADC0_IRQHandler
        PUBWEAK    CMP0_IRQHandler
        PUBWEAK    LPUART1_RxTx_IRQHandler
        PUBWEAK    LPUART0_RxTx_IRQHandler
        PUBWEAK    DefaultISR
        SECTION .text:CODE:REORDER:NOROOT(1)
DMA0_IRQHandler
DMA1_IRQHandler
DMA2_IRQHandler
DMA3_IRQHandler
DMA_Error_IRQHandler
ERM_fault_IRQHandler
RTC_IRQHandler
RTC_Seconds_IRQHandler
LPTMR0_IRQHandler
PORT_IRQHandler
CAN0_ORed_Err_Wakeup_IRQHandler
CAN0_ORed_0_31_MB_IRQHandler
FTM0_Ch0_7_IRQHandler
FTM0_Fault_IRQHandler
FTM0_Ovf_Reload_IRQHandler
FTM1_Ch0_7_IRQHandler
FTM1_Fault_IRQHandler
FTM1_Ovf_Reload_IRQHandler
FTFC_IRQHandler
PDB0_IRQHandler
LPIT0_IRQHandler
SCG_CMU_LVD_LVWSCG_IRQHandler
WDOG_IRQHandler
RCM_IRQHandler
LPI2C0_Master_Slave_IRQHandler
FLEXIO_IRQHandler
LPSPI0_IRQHandler
Reserved27_IRQHandler
ADC0_IRQHandler
CMP0_IRQHandler
LPUART1_RxTx_IRQHandler
LPUART0_RxTx_IRQHandler
DefaultISR
        B DefaultISR

        END

See this part of the FAQ (item #1) for help installing the correct vectors – specifically the part about three #define directives in FreeRTOSConfig.h.

Right. This is the section of the code you posted that installs the three handlers required by FreeRTOS:

        DCD   SVC_Handler                        ; Cortex-M0 SV Call Interrupt
        DCD   0
        DCD   0
        DCD   PendSV_Handler                     ; Cortex-M0 Pend SV Interrupt
        DCD   SysTick_Handler                    ; Cortex-M0 System Tick Interrupt

You can replace the default names for these handlers with the FreeRTOS handlers you have already brought into the file (although you would have to move the import of these symbols up above where you use them).

        EXTERN  vPortSVCHandler
        EXTERN  xPortPendSVHandler
        EXTERN  xPortSysTickHandler

So the same section of the vector table would look like this:

        DCD   vPortSVCHandler                        ; Cortex-M0 SV Call Interrupt
        DCD   0
        DCD   0
        DCD   xPortPendSVHandler                    ; Cortex-M0 Pend SV Interrupt
        DCD   xPortSysTickHandler                    ; Cortex-M0 System Tick Interrupt

Or just #define the default names for these handles to the FreeRTOS names, as per the link in the previous post.

Thank you. In both ways (following the above procedure or defining with FreeRTOS names), I am able to compile and link the files. But I have reset problems after these changes.

Following are the observations I have after and before modifying the code:
Case 1:

    PUBWEAK SVC_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

SVC_Handler
B vPortSVCHandler

    PUBWEAK PendSV_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

PendSV_Handler
B xPortPendSVHandler

    PUBWEAK SysTick_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

SysTick_Handler
B .

Then I am able to compile and link. Also,after downloading the out file, I am able to debug the functions “vPortSVCHandler” and “xPortPendSVHandler”. After reset, control is able to go Reset_Handler and thus able to execute “main()” function. But context switching is not happening as “xPortSysTickHandler” function is not involved any where.

Case 2:

    PUBWEAK SVC_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

SVC_Handler
B vPortSVCHandler

    PUBWEAK PendSV_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

PendSV_Handler
B xPortPendSVHandler

    PUBWEAK SysTick_Handler
    SECTION .text:CODE:REORDER:NOROOT(1)

SysTick_Handler
B xPortSysTickHandler

After branching to the function “xPortSysTickHandler” in SysTick_Handler, and defining these 3 handlers to the FreeRTOS names macros, I am able compile and link.
But after downloading, control is not going to reset handler. It’s going to “prvTaskExitError” and “prvIdleTask” functions. But here control is running all the tasks.

Please suggest where I am missing my changes?

Thanks and Regards,
Shashidhar

When you tried Case 1, did you follow this step?

Case 2 might actually be working. If your function that implements your task exits, you end up in prvTaskExitError(). Please note if you go with Case 2 (the #define strategy), you should revert to the original version of startup_S32K116.s (from IAR, is it?). You don’t need any changes to that file for the #define approach.

Hi team,

I have tried case 2 by using the original startup_S32K116.s file from IAR and defined the three handlers. I am able to compile and link. But still the issue with reset is not solved (as mentioned above). Also, if I use this way (defining the handlers with #define), I am not able to download using iSystem debugger as reset handler is not invoking.

Regards,
Shashidhar K

Can you explain? You are no longer able to download code into the MCU using the debugger?

Do you have an OS task that exits? In other words, does the function that implements the task end?

Hi,

As mentioned, using case 1 above, I am able to download the code using iSystem debugger and also when I reset it is going to reset handler. Here Context switching is not happening.

After doing the changes as per case 2 and download the software, reset is not happening and also, no further download is allowing using debugger. I am getting the error message “Failed to enter debug session.” Then using Cyclone tool, I am erasing the entire code and downloading it again.

Regarding OS task exits, all our tasks don’t exit. But, each task has continuous for loop. At the end of loop we call the function “vTaskDelayUntil” function with previous wake time and Time Increment values. Based on the priority of the tasks, switching between them will happen.

Here using case 2, I am seeing all the tasks are executing in the order, but when I do reset, the control is not going to reset handler. It is going to “prvTaskExitError” and “prvIdleTask” functions.

I would probably stick with “case 2” since it’s the most common way to integrate the handlers for Cortex M.

However, as a diagnostic test, you might want to remove your #define statements for the 3 handlers. Then FreeRTOS has no chance of running, but at least reset should work. Be sure to keep using the original IAR version of startup_S32K116.s.

I am confused that you say all the tasks are executing in order but reset doesn’t work. How are you inducing the reset that doesn’t work?

I am doing the reset using the debugger for both case 1 and case 2.

Does reset work if you remove the 3 #defines? Your code should end up stuck at B DefaultISR. And you should observe that reset works as expected.

Yes. Reset is working if I remove those 3 #defines and use original startup_S32K116.s file.

Ok now you have a good starting point.

  1. Please confirm that your code ended up stuck at B DefaultISR.
  2. Please confirm that a breakpoint at the beginning of main() is hit every time you reset.

Next step is add the following three lines to FreeRTOSConfig.h:

#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler
  1. Yes. Code got stuck at Default ISR and if I remove the break point from Default ISR, it is getting reset and control is going to Reset_handler.
  2. After Every reset, control is going to Reset_Handler and if I keep break point at the beginning of main() and run, it is getting hit every time.

Now I have added the 3 #defines and downloaded the new code. Just after download the control went to Reset_Handler. Then I hit Run in the debugger. It’s running and executing all the tasks. But when I do reset in the debugger while it is running, control is not going to reset handler and it is going to “prvTaskExitError” and “prvIdleTask” functions.

At this state, even downloading new software or loading the symbols also not working.

Please confirm that you are still using the original startup_S32K116.s, even with the #defines you added to FreeRTOSConfig.h.

How is program control going to two different places? Wouldn’t control end up in just one of those places?

It’s not going to two places. But at the place where control stops, I am seeing at one of these functions. But where ever it stops, In the call stack, I am seeing these functions.

Attached the image for reference.

The picture helps. That’s the normal call stack for the idle task (or for any task). That way if the task “returns” (which it should never do), control would end up prvTaskExitError().

So the idle task is running when you are trying to invoke reset. And for now it appears the debugger cannot invoke reset when in this condition.

Does the rest of your application continue to run, too? When in this condition is the tick still working? (Try a break point in xPortSysTickHandler() when in this condition.)

Yes. After reset, if I Run the code, I am seeing the tasks are executing (tried by keeping break point in individual tasks and also verified the order using task log).

But, as I am using original startup file and going through the #define approach, the symbol “xPortSysTickHandler” is not generated in the .map file. So, I can not keep the break point.

Also, please let me know how to verify if interrupt priorities are not handled correctly.