samd21 bootloader, application section and openocd

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

Working on a bootloader for the samd21.  Following the ASF and other examples I have setup a simple test program that turns on the LED and then jumps to application memory:

#define APP_START_ADDRESS          0x00002000

static void jumpToApplication(void);

int main(void)
{
	LED0_OFF;
	printf("Boot\n");
	LED0_ON;
	jumpToApplication();
	
	while (1) {
	}
}


static void jumpToApplication(void)
{
	uint32_t app_check_address;
	uint32_t *app_check_address_ptr;
	
	/* Check if WDT is locked */
	if (!(WDT->CTRL.reg & WDT_CTRL_ALWAYSON)) {
		/* Disable the Watchdog module */
		WDT->CTRL.reg &= ~WDT_CTRL_ENABLE;
	}
	
	app_check_address = APP_START_ADDRESS;
	app_check_address_ptr = (uint32_t *) app_check_address;
	
	/*
	 * Read the first location of application section
	 * which contains the address of stack pointer.
	 * If it is 0xFFFFFFFF then the application section is empty.
	 */
	if (*app_check_address_ptr == 0xFFFFFFFF) {
		while (1) {
			printf("Application section empty\n");
			/* Wait indefinitely */
		}
	}
	/* Pointer to the Application Section */
	void (*application_code_entry)(void);
	
	/* Rebase the Stack Pointer */
	__set_MSP(*(uint32_t *) APP_START_ADDRESS);
	
	/* Rebase the vector table base address */
	SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
	
	/* Load the Reset Handler address of the application */
	application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(APP_START_ADDRESS + 4));
	
	/* Jump to user Reset Handler in the application */
	application_code_entry();
}

I am using openocd and so I setup my configuration file as follows for putting the bootloader onto my chip:

init
targets
reset halt
at91samd bootloader 0
flash write_image erase hexfile
reset halt
at91samd bootloader 8192
verify_image hexfile
reset run
shutdown

This seems to work fine, I now want to have my application section start at the offset.  I can add the following linker option:

export LINKFLAGS += -Wl,--section-start=.text=0x2000

But then how do I get openocd to write without overwriting my bootloader, I have tried modifing the openocd configuration as follows:

init
targets
reset halt
flash write_image erase hexfile 8192
reset halt
verify_image hexfile 8192
reset run
shutdown

But it erases my bootloader section.  I have tried other combinations but haven't found what works yet.

Any insight is appreciated...

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

To follow up I have tried taking my bootloader.hex and combining with my application.hex by just removing the bootloader end line and then using openocd to write to the samd21 and the boot section does it thing, but then nothing happens once it jumps.  I have verified that I am jumping to the correct address in flash by hacking the first 32 bits of the application intel hex and printing them out.  So I am assuming there is something more that is needed for the application code then just:

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

Thanks in advance for the help.

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

My project uses openocd + gdb to write the images.  There's a 4k bootloader, and the image itself gets written to 0x1000.  The openocd commands I use are like this:

reset halt
at91samd bootloader 0
reset halt
flash write_image imagefile.bin 0x1000
at91samd bootloader 4096

Writing the bootloader itself looks exactly the same, except instead of 0x1000, the address is 0x0.  I think the problem you are having is that you're erasing the flash every time.

Last Edited: Wed. May 3, 2017 - 09:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the example, that is helpful.  For your bootloader, do you add an erase after flash write_image?

Also, I notice you use bin instead of hex.  I remember with avrdude we had to use bin instead of hex to get this kind of thing working.  If you put a hex in does it still work?

Thanks for the assistance.

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

photonthunder wrote:

Thanks for the example, that is helpful.  For your bootloader, do you add an erase after flash write_image?

Also, I notice you use bin instead of hex.  I remember with avrdude we had to use bin instead of hex to get this kind of thing working.  If you put a hex in does it still work?

Thanks for the assistance.

 

I don't actually build a hex in my project, so I couldn't say whether that works, and I've never used an AVR.  :)  I build an .elf and then use objcopy to turn that into a .bin.  Writing the bootloader uses exactly the same invocation, except with the bootloader filename and an address of 0x0 instead of 0x1000.

 

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

So you never actually do an erase?  I "assumed" that it was required, at least when you did the bootloader.  Thanks for the insight.

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

After some significant headaches I do have a minimal bootloader working that does allow me to flash the boot and application at the same time.  Some of my issues related to having a faulty external power supply and an old windows machine that also had a hard time producing enough current to run the boards without an external powered USB hub.  The final issue I had was that my bootloader code will not work if I set it to 0x4000 instead of 0x2000 (still trying to figure this one out - insight appreciated). Update, this addressing issue was mostly just doing a full erase after you make a mistake and write the application space to the wrong location.  It will then cause some havoc including changing fuses.

 

Methods for programming both the boot and application code using openocd that work for me are as follows:

  1. Take the boot.hex and the application.hex and combine them in one file (just remove the last line from the boot.hex).  Remember you have to shift the application code by adding section start in previous post above.
  2. Program the boot.hex and application.hex one after the other in the same openocd file, just remember to use erase with the boot flash_write and no erase with the application flash write.
  3. Program with boot.bin and application.bin in the same openocd file, just as you did with the hex files, but add the offset for the application.bin

Also, I removed the bootprotection from my openocd file since it was causing my fuses to get set to all FFs.  Mostly I believe because of my power issues.

Last Edited: Mon. Jun 5, 2017 - 10:01 PM