SAM V70 Bootloader incorrect program counter and stack pointer

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to develop a custom boot loader for the Atmel SAM4S and SAMV70, but am not meeting with much success.

 

I have seen a few other posts on forums around this issue, but having tried solutions from each post I have found, it's time for my own post.

 

So far my bootloader receives data over USB, and writes it into flash, starting at address 0x00420000, however it fails to launch my program as expected.

 

To eliminate the actual transmission and decoding of the application, I have also tried hard coding a small LED blink application into the bootloader itself as a const uint8_t array, to be written to flash, with the same result.

 

Written based on numerous forum posts, the Atmel bootloader example and the arm Keil documentation, this is my jumpToApp function:

//===============================================================================
static void jumpToApp( uint32_t *Address )
{
	 uint32_t stackPointerAddress = Address[0]; //*(uint32_t *)(FLASH_APP_START_ADDR);
 	uint32_t resetHandlerAddress = Address[1]; //*(uint32_t *)(FLASH_APP_START_ADDR + 4);

	 printf("Wait For Flash Ready \r\n");
 	while(!(EFC->EEFC_FSR & EEFC_FSR_FRDY));

	 printf("Stack Pointer: 0x%08X\r\nReset Handler: 0x%08X\r\n", stackPointerAddress, resetHandlerAddress);
	 printf("VTOR = 0x%08X\r\n", ( uint32_t )Address & SCB_VTOR_TBLOFF_Msk);

	 //------------------------------------------
	 // From ARM docs: http://www.keil.com/support/docs/3913.htm

	 // Make sure we're running priviliged
	 if(Tst_bits(SCB->SCR, FPU_FPCCR_USER_Msk))
	 {
		 Clr_bits(SCB->SCR, FPU_FPCCR_USER_Msk);
	 }

	 // Disable IRQ
         Disable_global_interrupt();

	 //Disable SysTick and clear its exception pending bit
	 SysTick->CTRL = 0 ;
	 SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk ;

	 /** Release Resources before jumping to User Application */
	 sysclk_disable_peripheral_clock(ID_UART1);
	 sysclk_disable_peripheral_clock(ID_TWIHS0);
	 udc_stop();

	 /** Barriers */
	 __DSB();
	 __ISB();

	 // Load the vector table address of the user application into the SCB->VTOR register
	 SCB->VTOR =  ( uint32_t )Address & SCB_VTOR_TBLOFF_Msk;

	 /** Barriers */
	 __DSB();
	 __ISB();

	 // Set the MSP to the value found int he User Application vector table
	 __set_MSP( stackPointerAddress ) ;

	 // Set the PC to the reset vector value of the user application via a function call.
	 ( ( void ( * )( void ) )resetHandlerAddress )( ) ;

	 // should never get here
	 while(1)
	 {
		 printf("Reboot Failed\r\n");
		 delay_ms(500);
	 }
	 //------------------------------------------
}

 

When I run and debug this, I can see that the initial stack pointer in the new vector table (in flash) is 0x204024F0, and the reset vector address is 0x004205ED, which both seem reasonable.

 

Stepping through, when execution is meant to have jumped to my application, I can see that the Program Counter is sat at 0x004205E8, which is 5 bytes behind where it should be. The Stack Pointer also appears to be slightly off, reading 0x204024C0 instead of 0x204024F0.

Dissassembly shows execution sitting at :

004205E8   b #-4

and never moving away.

The firmware I have written to flash is taken directly from the Intel Hex file generated by Atmel Studio 7.0, compiled with the linker offset flag:

-Wl,--section-start=.text=0x00420000

I have also tried directly editing the linker script rom origin and length fields:

rom (rx)  : ORIGIN = 0x00420000, LENGTH = 0x000A0000

 

I am new to bootloaders, and have reached the limits of my understanding of low level cpu execution to provide more observation than the above, so any help or observations would be greatly appreciated!

Last Edited: Tue. Jun 5, 2018 - 01:38 PM