Secondary Bootloader on Cortex-M0

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

Secondary Bootloader on Cortex-M0

4,370 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mmoyano on Thu Jul 01 15:34:27 MST 2010
Hello

Today I am finishing a project based on LPC1113. This hardware needs to update its firmware using the IAP subroutines. I wrote  a secondary bootloader wich size is less than 4KB and it can be stored in the sector 0.
The secondary bootloader is working very well and it can write the user application from sector 1. Below you can see the memory map:

//  ------------------------
// |                        |0x0000 0000
// |    BOOT VECTOR TABLE   |
// |                        |0x0000 00BF
// |------------------------|
// |                        |0x0000 00C0
// |                        |
// |                        |
// |       BOOTLOADER       |
// |                        |
// |                        |0x0000 0FFF
// |------------------------|
// |                        |0x0000 1000
// |   USER VECTOR TABLE    |
// |                        |0x0000 10BF
// |------------------------|
// |                        |0x0000 10C0
// |        JUMPS           |
// |                        |0x0000 12B0
// |------------------------|
// |                        |0x0000 12B4
// |                        |
// |    USER APPLICATION    |
// |                        |
// |                        |
// |                        |
// |                        |
// |                        |
// |                        |
// |                        |0x0000 5FFF
//  ------------------------

Since the Cortex-M0 is not able to change the interrupt vectors, I wrote a code that remaps this vector table to another vector table (USER VECTOR TABLE) from sector 1.
But since in the USER VECTOR TABLE the compiler generates addresses of functions pointing to the interrupt routines, I changed almost all address interrupts in BOOT VECTOR TABLE where each address will be the address of "BRANCHS INSTRUCTIONS" from the user interrupt routine. I call this area as "JUMPS".
So, when an interrupt occurs, the Cortex-M0 takes one address from BOOT VECTOR TABLE that point to one entry in JUMPS and then I wrote assembler code to achieve a branch to the real user interrupt routine that I could be found using the USER VECTOR TABLE.

You can see the attached file with extra info.

Finaly I ran all the code (bootloader + user application) and I found that on each interruptions, the debugger is stopped on IntDefaultHandler, I am assuming that I have a bad address somewhere but anyway, I think that also the stack is changed on each interruptions because in my JUMPS sections, I am changing the LR register and I think that is another possible error for this implementation.

I hope that you can help me with this complex issue.

Thanks in advance!
0 Kudos
Reply
9 Replies

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rama krishna deekshitulu on Thu Feb 25 06:02:51 MST 2016

Quote: mmoyano
Hi mmoyano

I would like to clarify my current situation, my code is split into two parts. The boot loader flashes an OTA upgrade using IAP and then jumps to the newly flashed code. My issue starts at this point where jumping to the new code sector using assembly to load the appropriate registers (SP & PC) with address to the values at the new application SP and PC locations.

New application code without SysTick runs fine and works normal but code that includes it tends to freeze.Do i need to do something specific to use SysTick timer with the secondary boot loader.

Does the application code need a specific sequence of code to use SysTick after jumping from bootloader or is this something that needs to be done before jumping to application in the bootloader.

0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by rama krishna deekshitulu on Thu Feb 18 00:12:01 MST 2016
Hi mmoyano
I am done a project based on LPC1225 This hardware needs to update its firmware using the IAP subroutines. The secondary bootloader is working fine and it can write the user application from sector 3. if i am USING SYSTEM TICKTIMERS  the code is blocked at delay function please check this code and help me...below attached  bootloader application is secondary  bootloader
0 Kudos
Reply

2,584 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mmoyano on Thu Oct 07 08:57:32 MST 2010
Hi baranikumarhtsl

I am wondering if you could post some of the code to understand the main function. I am going to try to help you with this issue.

Regards!
0 Kudos
Reply

2,584 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by baranikumarhtsl on Wed Oct 06 05:47:31 MST 2010
Hi,

I have tried changing the SYSMEMREMAP from flash to RAM before jumping to user-program using the sample snippet available in this thread. But the problem is i am not able to execute the interrupts in my user-application. It would be great if you can share the piece of your code showing how your user-application is able to make use of the interrupts!...
0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mmoyano on Mon Jul 05 19:49:48 MST 2010
Thank you curtvm and klatecki

The issue is solved and is perfectly working. Both solutions is OK:

A) An implementation of an user vector table with a "JUMPS" section to achieve a branch between the original vector table on bootloader and the secondary vector table on user application.
B) An Implementation of a remapping of secondary vector table to ram (0x10000000).

I had two mistakes, first I wrote bad the BOOT VECTOR TABLE, you can see that the 18º position was copy two times (see extra info file) but in addition, I had to use the MOV instruction with the PC register to achive a real JUMPS between each vector tables. By correcting both errors, the solution is working.
Second, one  day I wrote some of code to test the remapping of the vector table to RAM and I do not remember what was my error but then I came to write again this code and is working now. Below it is find the basic code to remap the vector table:


int32 vector_in_ram[52] __attribute__ ((section ("vtable")));

// _________________________________________________________________
int main(void)
{
int i;
int32 *p = (int32 *) 0x1000;

__disable_irq();
// copy the interrupt vector table on base RAM
for (i=0;i<52;i++)
{
vector_in_ram = *(p + i);
}
LPC_SYSCON->SYSMEMREMAP = 0x1; 



Below you can see some extract of JUMPS function with the MOV instruction used:

void __jumps(void) __attribute__ ((naked, used, section(".jumps")));
// _________________________________________________________________
void __jumps(void)
{
__asm("ldr r3,=0x1000"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x1004"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x1008"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x100C"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");

__asm("ldr r3,=0x1010"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x1014"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x1018"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");
__asm("ldr r3,=0x101C"); __asm("ldr r2,[r3]"); __asm("mov pc,r2");




Well, both solutions is working now and I am happy. I hope that this issue can be help to someone else.

Thanks again to curtvm and klatecki. They helped me a lot.

Regards!
0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by klatecki on Mon Jul 05 14:11:46 MST 2010

Quote: curtvm
This is an lpc1113 we are talking about.



sorry, my mistake
0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by curtvm on Mon Jul 05 10:49:36 MST 2010
This is an lpc1113 we are talking about, which doesn't have the ability to remap the vector table as the M3 does.

To use sram instead of flash for the vector table, look up section 4.1 in the user manual (SYSMEMREMAP).
0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by klatecki on Mon Jul 05 05:55:04 MST 2010
Read about the register SCB-> VTOR and do it straight rather than around
0 Kudos
Reply

2,585 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by curtvm on Sun Jul 04 10:37:41 MST 2010
I am not an expert on this, but I don't think you want a BLX in your 'jumps', as it then becomes a 'call', not a 'jump' (and I think you will end up back in your jump table on the 'return').

Check out what the C compiler produces for this-
    void TIMER32_0_IRQHandler(void);
    goto *&TIMER32_0_IRQHandler;

which is something like-
     1d4:    4b00          ldr    r3, [pc, #0]
     1d6:    469f          mov    pc, r3
     1d8:    000000c1     .word    0x000000c1

that would be a true 'jump' (I'm not sure why BX isn't used, or if there is any difference with the MOV used instead).

The vector table CAN be moved to ram, also.
0 Kudos
Reply