Bootloader. VTOR, BOOTPROT FUSE, JUMP to app and other related questions

Hello everyone!

I am writing here because I am having some issues developing my own bootloader. I am currently working with an ATMEL SAM R21 which has an ARM CORTEX M0+ in it.

Firstly I am going to summarize the more relevant points (or I think those are the most relevant ones):

1) Write appropriately in FLASH MEMORY. It is already done and working.

2) Relocate vector table. The Bootloader has been though to be at the first part of the memory, so immediately after the vector table and other. The reset vector is the starting point

I think, so I pretend to use in the code the VTOR (vector table offset register) in order to change it right before jumping to the application address.

As the application is going then to start at the 0x0000_2000 address, just before jump I set the VTOR like this:

SCB->VTOR = ((uint32_t)0x00002000 );

Edited 22-06-2016 10:18 a.m.:

I noticed that as I try to modify the VTOR as in the previous lines, the application leads me to the Hard_fault debugger, so maybe it can be modified like this. I tried to modify its value before and after initializing the board

3) BOOTPROT FUSE. I has been only able to modify this use using the ATMEL STUDIO, is there any other way? For example something like this:

uint32_t *bootprot = NULL;

*bootprot = *(uint32_t *)NVMCTRL_FUSES_BOOTPROT_ADDR;

*bootprot = *bootprot | NVMCTRL_FUSES_BOOTPROT(2);

I say this because in production maybe is a bit messy to use the ATMEL STUDIO in order to set the memory where the BOOTLOADER is going to be stored. Is there another way for

modifying this FUSE? In the datasheet there are continous references to the NVM, but I don't know if it would be practical to write it like this.

4)Jump to the application. I have seen many examples but with this function would it be enough???

void start_application( uint32_t app_link_location )

{

  asm(" ldr r1, [r0,#0]"); // get the stack pointer value from the program's reset vector

  asm(" mov sp, r1");      // copy the value to the stack pointer

  asm(" ldr r0, [r0,#4]"); // get the program counter value from the program's reset vector

  asm(" mov r0, #0");

  asm(" blx r0");          // jump to the start address

}

or

void jump_to_application( void )

{

  typedef int(*fn_prt_t)(void);

  fn_prt_t main_prog;

  main_prog= (fn_prt_t)0x00002000;

  main_prog();

}

In the star_application I don't know why is needed more directives than the last one. If I just access the function R0 has the for example 0x2000 value got as parameter, so

I should be able to jump there, shouldn't I?. I don't really know if I should store something or what, or if just jumping would be enough.

I should point out that as the BOOTLOADER is going to be approximately 8K size, I set the BOOTPROT FUSE to 0x2 value for this purpose, but I don't notice anything different after

setting it to such value.

5) Flash both bootloader and application. Well, I have modified the linker files in order to indicate that the bootloader should be in the following address range:

0x0000_0000 to 0x0000_1FFF.

The application:

0x0000_2000 to 0x0003_FFFF

If I use the JTAG and the IAR in order to load the application/firmware it seems that erases the memory before programing anything, so I only find 2 alternatives but I don't know

how can I carry them out:

Build a binary with the bootloader and the application in it using an external tool which merges both .hex in one .bin or something like that.

Does BOOTPROT protect the memory? So I am maybe able to program the bootloader, change the BOOTPROT FUSE from 0x7 to 0x2 (to protect 8K memory and set aside that amount of memory

for the bootloader) and maybe trying to expect that now as I program the application the bootloader will remain on memory. This is for sure just not working like this, isn't it?

I will very appreciate any advice you could provide me.

Thank you very much.

Iván.

Message was edited by: Iván

More questions in this forum