7 years, 3 months ago.

ARM GCC toolchain not initializing RTOS (was: simple RTOS example ends in HardFault_Handler)

Hi,

I tried running the RTOS Thread example on LPC1768, but when creating a Thread, a HardFault occurred. It happens always if the code was compiled with ARM GCC.

Callstack

>   HardFault_Handler()
    <signal handler called>()   
    SVC_Handler()
    <signal handler called>()   
    __svcMutexWait()
    osMutexWait()
    rtos::Mutex::lock()
    rtos::Thread::start(mbed::Callback<void ()>)()
    rtos::Thread::constructor(mbed::Callback<void ()>, osPriority, unsigned long, unsigned char*)()
    rtos::Thread::Thread()
    main()

The SVC_Handler() causes the exception when executing line 10 of the following partial code listing, because the PSP contains an uninitialized random invalid value:

HAL_CM3.S (partyl)

SVC_Handler:
        .ifdef  IFX_XMC4XXX
        .global SVC_Handler_Veneer
SVC_Handler_Veneer:
        .endif
        .fnstart
        .cantunwind
 
        MRS     R0,PSP                  /* Read PSP */
        LDR     R1,[R0,#24]             /* Read Saved PC from Stack */
        LDRB    R1,[R1,#-2]             /* Load SVC Number */
        CBNZ    R1,SVC_User
 
        LDM     R0,{R0-R3,R12}          /* Read R0-R3,R12 from stack */
        BLX     R12                     /* Call SVC Function */

After some debugging I found out, that the startup file does not initialize the RTOS component. This may also be the issue while people have trouble running code compiled with CodeSourcery.

Maybe somebody could forward it to the mbed-os developers so it can be integrated into one of the following releases?

A replacement startup file (.c instead of .S) could be:

startup_LPC17xx.c

/*----------------------------------------------------------------------------
    Description: LPC17xx startup file for ARM GCC compilers
    Copyright:   unknown, files did not contain any copyright info
    License:     unknown, files did not contain any license info
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Note: This file is a adption of the basic startup code from Sysprogs
          (ORIGINAL_CR_startup_lpc175x_6x.c), extended with functionality from
          mbed TOOLCHAIN_GCC_CR (startup_LPC17xx.cpp) to call the necessary
          routines to run CMSIS RTOS/RTX from mbed.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------*/

// common defintions
#define NULL ((void *)0)

// Local functions
void Reset_Handler();
void Default_Handler();

// External functions
extern void SystemInit(void);
extern void pre_main(void) __attribute__((weak));
extern void software_init_hook(void);
extern void __libc_init_array(void);  // this comes from newlib-nano
extern int main(void);

// The following external defintions are part of the linker script
extern void* __StackTop;
extern void* __etext;
extern void* __data_start__;
extern void* __data_end__;
extern void* __bss_start__;
extern void* __bss_end__;

// Interrupt handler defintions with weak Default_Handlers
void NMI_Handler()             __attribute__((weak, alias("Default_Handler")));
void HardFault_Handler()       __attribute__((weak, alias("Default_Handler")));
void MemManage_Handler()       __attribute__((weak, alias("Default_Handler")));
void BusFault_Handler()        __attribute__((weak, alias("Default_Handler")));
void UsageFault_Handler()      __attribute__((weak, alias("Default_Handler")));
void SVC_Handler()             __attribute__((weak, alias("Default_Handler")));
void DebugMon_Handler()        __attribute__((weak, alias("Default_Handler")));
void PendSV_Handler()          __attribute__((weak, alias("Default_Handler")));
void SysTick_Handler()         __attribute__((weak, alias("Default_Handler")));
void WDT_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void TIMER0_IRQHandler()       __attribute__((weak, alias("Default_Handler")));
void TIMER1_IRQHandler()       __attribute__((weak, alias("Default_Handler")));
void TIMER2_IRQHandler()       __attribute__((weak, alias("Default_Handler")));
void TIMER3_IRQHandler()       __attribute__((weak, alias("Default_Handler")));
void UART0_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void UART1_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void UART2_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void UART3_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void PWM1_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void I2C0_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void I2C1_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void I2C2_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void SPI_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void SSP0_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void SSP1_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void PLL0_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void RTC_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void EINT0_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void EINT1_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void EINT2_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void EINT3_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void ADC_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void BOD_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void USB_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void CAN_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void DMA_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void I2S_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void ENET_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void RIT_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void MCPWM_IRQHandler()        __attribute__((weak, alias("Default_Handler")));
void QEI_IRQHandler()          __attribute__((weak, alias("Default_Handler")));
void PLL1_IRQHandler()         __attribute__((weak, alias("Default_Handler")));
void USBActivity_IRQHandler()  __attribute__((weak, alias("Default_Handler")));
void CANActivity_IRQHandler()  __attribute__((weak, alias("Default_Handler")));

// The Interrupt Vector table                                                       
void* g_pfnVectors[0x33] __attribute__((section(".isr_vector"))) = 
{
    &__StackTop,               // Top of Stack
    &Reset_Handler,            // Reset Handler
    &NMI_Handler,              // NMI Handler
    &HardFault_Handler,        // Hard Fault Handler
    &MemManage_Handler,        // MPU Fault Handler
    &BusFault_Handler,         // Bus Fault Handler
    &UsageFault_Handler,       // Usage Fault Handler
    NULL,                      
    NULL,                      
    NULL,                      
    NULL,                      
    &SVC_Handler,              // SVCall Handler
    &DebugMon_Handler,         // Debug Monitor Handler
    NULL,
    &PendSV_Handler,           // PendSV Handler
    &SysTick_Handler,          // SysTick Handler
    &WDT_IRQHandler,           // 16: Watchdog Timer
    &TIMER0_IRQHandler,        // 17: Timer0
    &TIMER1_IRQHandler,        // 18: Timer1
    &TIMER2_IRQHandler,        // 19: Timer2
    &TIMER3_IRQHandler,        // 20: Timer3
    &UART0_IRQHandler,         // 21: UART0
    &UART1_IRQHandler,         // 22: UART1
    &UART2_IRQHandler,         // 23: UART2
    &UART3_IRQHandler,         // 24: UART3
    &PWM1_IRQHandler,          // 25: PWM1
    &I2C0_IRQHandler,          // 26: I2C0
    &I2C1_IRQHandler,          // 27: I2C1
    &I2C2_IRQHandler,          // 28: I2C2
    &SPI_IRQHandler,           // 29: SPI
    &SSP0_IRQHandler,          // 30: SSP0
    &SSP1_IRQHandler,          // 31: SSP1
    &PLL0_IRQHandler,          // 32: PLL0 Lock (Main PLL)
    &RTC_IRQHandler,           // 33: Real Time Clock
    &EINT0_IRQHandler,         // 34: External Interrupt 0
    &EINT1_IRQHandler,         // 35: External Interrupt 1
    &EINT2_IRQHandler,         // 36: External Interrupt 2
    &EINT3_IRQHandler,         // 37: External Interrupt 3
    &ADC_IRQHandler,           // 38: A/D Converter
    &BOD_IRQHandler,           // 39: Brown-Out Detect
    &USB_IRQHandler,           // 40: USB
    &CAN_IRQHandler,           // 41: CAN
    &DMA_IRQHandler,           // 42: General Purpose DMA
    &I2S_IRQHandler,           // 43: I2S
    &ENET_IRQHandler,          // 44: Ethernet
    &RIT_IRQHandler,           // 45: Repetitive Interrupt Timer
    &MCPWM_IRQHandler,         // 46: Motor Control PWM
    &QEI_IRQHandler,           // 47: Quadrature Encoder Interface
    &PLL1_IRQHandler,          // 48: PLL1 Lock (USB PLL)
    &USBActivity_IRQHandler,   // 49: USB Activity
    &CANActivity_IRQHandler,   // 50: CAN Activity
};


// Reset_Handler(): Entry point after reset
void __attribute__((naked, noreturn)) Reset_Handler()
{
    // Copy initialized RAM section from Flash
    void **pSource, **pDest;
    for (pSource = &__etext, pDest = &__data_start__; pDest != &__data_end__; pSource++, pDest++)
        *pDest = *pSource;
    
    // Initialize BSS section in RAM
    for (pDest = &__bss_start__; pDest != &__bss_end__; pDest++)
        *pDest = 0;

    // Run system intialization
    SystemInit();
    
    if (pre_main)
    {
        // give control to the RTOS
        software_init_hook(); // this will also call __libc_init_array
    }
    else
    {
        // for BareMetal (non-RTOS) build
        __libc_init_array();
        (void)main();
    }
    
    // done - this should never be reached
    for (;;) ;
}


// The Default_Handler that gets executed if your code is missing an interrupt handler
void __attribute__((naked, noreturn)) Default_Handler()
{
	//If you get stuck here, your code is missing a handler for some interrupt.
    for (;;) ;
}
Be the first to answer this question.