Bootloader and FreeRTOS hardfault

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Bootloader and FreeRTOS hardfault

3,289 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Wed Mar 18 04:03:30 MST 2015
Hello all,

I have a bootloader on my LPC1833 to jump to my application code.

When I put a basic application code (blinking LED), the bootloader can jump to the application and it runs well. When I set a FreeRTOS application code, i have an HardFault after jumping to the application code.

I read many threads of people who had the same problem on other target but I can't find a solution for me. The threads were focus on the Vector Table.

Do you have any idea?

Regards,

Arnaud
Labels (1)
0 Kudos
9 Replies

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by chrta on Sat Jun 06 01:34:27 MST 2015

Quote: ArnaudE

...
Although i used a general function to disable interrupt, the Ethernet one was still enable (may some specific interrupt are disable and not all).
...


Have you set the interrupt priority for ethernet correctly? See http://www.freertos.org/FAQHelp.html and http://www.freertos.org/RTOS-Cortex-M3-M4.html
0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Mon Mar 30 07:09:12 MST 2015
To sum up, i have an Ethernet bootloader and an application code with FreeRTOS. The Ethernet bootloader is used to update the application code. When jumping to the application I had some trouble and now everything works.

If you are using an Ethernet Bootloader, and FreeRTOS Ethernet taks (and lwip), do not forget to disable the Ethernet interrupt in the bootloader before jumping to application code. Although i used a general function to disable interrupt, the Ethernet one was still enable (may some specific interrupt are disable and not all).

Regards,

Arnaud
0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Thu Mar 19 05:41:37 MST 2015
Hi,

I change my application code commenting FreeRTOS task creation and just let a FreeRTOS task that toggle a LED. FreeRTOS is running well. Step by step i will uncommented other FreeRTOS task to see where the problem is.

For people in need, this is how i jump to the application code (some code comes from people who also had problem jumping to FreeRTOS application)

void boot_jump( uint32_t address )
{
  __ASM volatile ("MOV LR, #0xFFFFFFFF"); //Reset Link Register
  __ASM volatile ("LDR SP, [R0]"); //Load new stack pointer address
  __ASM volatile ("LDR PC, [R0, #4]");//Load new program counter address
}

void jumpToProgram (uint32_t address)
{
        SCB->VTOR = address & 0x3FFFFF80;
        boot_jump(address);
}

void execute_bank_a_user_code(void)
{    
    /* Disable SysTick timer   */
    SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
    /* Disable INT */
    disable_interrupts();
    
    jumpToProgram((uint32_t)USER_START_SECTOR_ADDRESS);
}


1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Wed Mar 18 10:13:09 MST 2015
This is the complete function from FreeRTOS. pxNewTCB->pxStack seems to be valid because it passes the conditions.

static TCB_t *prvAllocateTCBAndStack( const uint16_t usStackDepth, StackType_t * const puxStackBuffer )
{
TCB_t *pxNewTCB;

/* Allocate space for the TCB.  Where the memory comes from depends on
the implementation of the port malloc function. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );

if( pxNewTCB != NULL )
{
/* Allocate space for the stack used by the task being created.
The base of the stack memory stored in the TCB so the task can
be deleted later if required. */
pxNewTCB->pxStack = ( StackType_t * ) pvPortMallocAligned( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ), puxStackBuffer ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */

if( pxNewTCB->pxStack == NULL )
{
/* Could not allocate the stack.  Delete the allocated TCB. */
vPortFree( pxNewTCB );
pxNewTCB = NULL;
}
else
{
/* Avoid dependency on memset() if it is not required. */
#if( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) )
{
/* Just to help debugging. */
( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );
}
#endif /* ( ( configCHECK_FOR_STACK_OVERFLOW > 1 ) || ( ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) ) ) */
}
}

return pxNewTCB;
}


I will check the .bss section.
0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Wed Mar 18 10:06:38 MST 2015

Quote:
May I have a stack problem because I have the hardfault after FreeRTOS call the function "prvAllocateTCBAndStack", at this point



The stack allocated in the function actually comes from the .bss section - it is not the stack allocated by the compiler.  The fact accessing that memory is giving the hard fault is a big clue though.  Is the value of pxNewTCB->pxStack at that point valid?  That is, within the .bss section of the application and in a valid RAM area of the memory map?

0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Wed Mar 18 09:52:47 MST 2015

Quote:
- I note you globally disable interrupts before the jump.  That should be ok, but to make sure, have you tried enabling them again in the main() of the function you are jumping to?


Yes.


Quote:

- What happens to the stack?  The stack is [effectively] read from the top of the vector table.  Do both vector tables have the same stack defined?


May I have a stack problem because I have the hardfault after FreeRTOS call the function "prvAllocateTCBAndStack", at this point :

( void ) memset( pxNewTCB->pxStack, ( int ) tskSTACK_FILL_BYTE, ( size_t ) usStackDepth * sizeof( StackType_t ) );



Quote:

- Does the code you are jumping to have its own C run time environment code, so it does things like zero out the bss and copy initialised data, etc.


Yes


Quote:

- [relevant to the previous question] Why do you jump to the application code using a function call rather than branch?


I just changed to a branch.

I'm not very comfortable with bootloader, I just started working on it.
0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Wed Mar 18 08:46:33 MST 2015
I've never done it myself, so can't be sure, just read lots of posts on the FreeRTOS support forum where other people have done it.  I would have thought it was right though.  A couple of comments:

- I note you globally disable interrupts before the jump.  That should be ok, but to make sure, have you tried enabling them again in the main() of the function you are jumping to?

- What happens to the stack?  The stack is [effectively] read from the top of the vector table.  Do both vector tables have the same stack defined?

- Does the code you are jumping to have its own C run time environment code, so it does things like zero out the bss and copy initialised data, etc.

- [relevant to the previous question] Why do you jump to the application code using a function call rather than branch?

0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ArnaudE on Wed Mar 18 08:37:33 MST 2015
Thanks for you help.

In the bootloader I use the Systick timer, so i disable it before jumping to application code. Then I set the vector table pointer to the USER_START_SECTOR_ADDRESS (which is the start address of the vector table of the application code) and then I jump to the application. Am i doing it wrong?

void execute_bank_a_user_code(void)
{
    fcall *temp;
    
    /* Disable SysTick timer                                                    */
    SysTick->CTRL &= ~(SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk);
    /* Disable INT */
    disable_interrupts();
    
    /* Set vector table pointer */
    SCB->VTOR = ((uint32_t)USER_START_SECTOR_ADDRESS);
    
    temp = (fcall*) (USER_START_SECTOR_ADDRESS | 0x00000004) ;
    (*temp)();    
}


Regards,
Arnaud
0 Kudos

1,895 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by www.FreeRTOS.org on Wed Mar 18 07:45:02 MST 2015
You are right, when people report problems with boot loaders it nearly always turns out to be an issue with the vector table.

FreeRTOS uses the SVC, SysTick and PendSV interrupts, and must have the appropriate handlers installed.  Does your boot loader use the same interrupts?  Do you reprogram the vector base register to point to the vector table that has the FreeRTOS handlers installed when jumping to the application code?

0 Kudos