SAMS70 app crashing when bootloader used

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all

I have an application that runs on SAMS70. I just recently implemented a bootloader to support firmware update through UART connection to PC. The bootloader is based on the "SafeAndSecureBootloader" example from Atmel/Microchip, but uses the UART and custom messaging to update the firmware.

 

Now it seems like after introducing the bootloader the application usually crashes within minutes after startup - it ends up in the Dummy_handler() ISR but the stack frame looks quite strange and also seems different at each crash and I haven't been able to get anything useful from it (although I haven't spend much time on it). The only thing I could see was that Interrupt Program Status Register had value 3 which indicates "hard fault".

 

I have two concerns. First of all, the bootloader does of course initialize some peripherals (UART, timers, etc). How can I be sure that none of that causes problems in the main application? I want the peripherals to be more or less untouched after reset once the main application starts so I tried the following:

- when bootloader starts it checks for valid application in flash

- valid application found and no other flags indicate control should stay in bootloader it will try to invoke the main application

- to invoke the main application the bootloader first writes a special signature in SRAM and then initiates a watchdog reset

- after reset the bootloader checks for the signature and if set it skips most of the hardware initialization and jumps into main application

 

This way there is a minimum of hardware initialization done between watchdog reset and start of main application. But it seems it did not help in my case...

 

Second - how should I proceed with debugging? How can I trace back to where the fault occurred?

 

 

 

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems like this was not related to the bootloader. I tried running the application standalone and discovered that it crashed immediately at first line of main().

 

After moving back and forth in SVN history I found that the addition of one of the functions made the application crash, but the function itself was not called at run-time. Then I saw that the application size was now just above 64k. I then tried switching to the Release configuration (size approx 58 kB) which seemed to run fine!

 

So for some reason the application does not work properly when size grows beyond 64k. I have no idea why!?

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So I looked at the disassembly when crashing and apparently it is a "vpush" instruction that is the root cause of the exception:

00411b40 <main>:
{
  411b40:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
  411b44:	ed2d 8b02 	vpush	{d8}
  411b48:	b0a5      	sub	sp, #148	; 0x94
	atmel_start_init();

I looked it up and noticed that vpush is related to the FPU. I then remembered that I had previously noted that the startup code in my application differed from the one in the SafeAndSecureBootloader in one aspect - there was no call to fpu_enable() in my application. So i tried adding it and now it does seem to run fine! Here is my reset handler now:


/**
 * \brief This is the code that gets called on processor reset.
 * To initialize the device, and call the main() routine.
 */
void Reset_Handler(void)
{
        uint32_t *pSrc, *pDest;

        /* Initialize the relocate segment */
        pSrc = &_etext;
        pDest = &_srelocate;

        if (pSrc != pDest) {
                for (; pDest < &_erelocate;) {
                        *pDest++ = *pSrc++;
                }
        }

        /* Clear the zero segment */
        for (pDest = &_szero; pDest < &_ezero;) {
                *pDest++ = 0;
        }

        /* Set the vector table base address */
        pSrc = (uint32_t *) & _sfixed;
        SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);

#if __FPU_USED          // ADDED
    _fpu_enable();      // ADDED
#endif                  // ADDED

        /* Initialize the C library */
        __libc_init_array();

        /* Branch to main function */
        main();

        /* Infinite loop */
        while (1);
}

 

So how come older versions work? I tried going back to a working version and noticed that in that case there was no "vpush" at all before call to atmel_start_init() which does in turn call _fpu_enable():


00405af0 <main>:
{
  405af0:	e92d 4ff0 	stmdb	sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
  405af4:	b0a5      	sub	sp, #148	; 0x94
	atmel_start_init();

 

So my conslusion is that when code size grows beyond 64k (or perhaps for some other reason?) the compiler inserts a "vpush" at start of main(). This will generate an exception if FPU has not been enabled already in startup code.

 

 

 

/Jakob Selbing

Last Edited: Tue. Nov 5, 2019 - 01:09 PM