Divide Bootloader and application

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

Divide Bootloader and application

2,531 Views
ajn
Contributor I
 Hello!

I need to divide bootloader code and application code in two separate projects, and I like to program both the bootloader and the application in C.

When the bootloader is finish it shall reboot and when it starts again, It shall jump to the application. But before the application starts it need to be initialized. How shall I do this? Should the bootloader jump to the function _Startup() in the application?

Is it OK to have two of this function, one in the bootloader and one in the application? If not how do I initialize the main application, if I like to use ANSI initializing?

How do I set an absolute address of the _Startup()  function (or any function) in the application project that newer changes so the bootloader always finds it and jumps to this address when it is finish?

Will the struct _tagStartup _startupData contain correct data so the segments .text .bss .data etc, are correctly found and the corresponding variables are correctly initialized?  

I need also handle the interrupt vector table. The bootloader will only use the reset vector. And I know that I can use the jump table support to redirect the addresses in interrupt vector table to this jump table, but what happens if we start to use expert mode programming when we add new code to the application how do we tell that this Interrupt addresses shall be placed in the jump table and not in the interrupt vector table.

Do we need to handle this manually, how do we do that? Several people will write code so it may be dangerous if we need to manually edit the jump table.

 

Today I use this method to handle IRQ. How do I Add the jump table here?

 

void (* const _vect[])() @0xFFCC = {   /* Interrupt vector table */
         UNASSIGNED_ISR,               /* Int.no. 25 Vrti (at FFCC)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 24 Viic1 (at FFCE)                 Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 23 Vatd1 (at FFD0)                 Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 22 Vkeyboard1 (at FFD2)            Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 21 Vsci2tx (at FFD4)               Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 20 Vsci2rx (at FFD6)               Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 19 Vsci2err (at FFD8)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 18 Vsci1tx (at FFDA)               Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 17 Vsci1rx (at FFDC)               Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 16 Vsci1err (at FFDE)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 15 Vspi1 (at FFE0)                 Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 14 Vtpm2ovf (at FFE2)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 13 Vtpm2ch4 (at FFE4)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 12 Vtpm2ch3 (at FFE6)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 11 Vtpm2ch2 (at FFE8)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 10 Vtpm2ch1 (at FFEA)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  9 Vtpm2ch0 (at FFEC)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  8 Vtpm1ovf (at FFEE)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  7 Vtpm1ch2 (at FFF0)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  6 Vtpm1ch1 (at FFF2)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  5 Vtpm1ch0 (at FFF4)              Unassigned */
         isrVicg,                      /* Int.no.  4 Vicg (at FFF6)                  Used */
         UNASSIGNED_ISR,               /* Int.no.  3 Vlvd (at FFF8)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  2 Virq (at FFFA)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  1 Vswi (at FFFC)                  Unassigned */
         _Startup                      /* Int.no.  0 Vreset (at FFFE)                Reset vector */
 };

 

Do we need to set any registers to tell the the compiler and linker that we use the jump table?

The processor is: MC9S08GB60, and I use Codewarrior IDE 5.7.0

 

Ake

 

 

 

 

 

 

Labels (1)
0 Kudos
2 Replies

386 Views
CompilerGuru
NXP Employee
NXP Employee
When the bootloader is finish it shall reboot and when it starts again, It shall jump to the application. But before the application starts it need to be initialized. How shall I do this? Should the bootloader jump to the function _Startup() in the application?

Yes :smileyhappy:

Is it OK to have two of this function, one in the bootloader and one in the application?

As the two applications are compiled separately, there are no name conflicts.

If not how do I initialize the main application, if I like to use ANSI initializing?

How do I set an absolute address of the _Startup()  function (or any function) in the application project that newer changes so the bootloader always finds it and jumps to this address when it is finish?

Your main application does needs its own vector table anyway, so I would just place its _Startup at the reset entry of this secondary vector table.

Will the struct _tagStartup _startupData contain correct data so the segments .text .bss .data etc, are correctly found and the corresponding variables are correctly initialized? 

Sure. Basically the loader _Startup will find its own loader _startupData and the main apps _Startup its own _startupData, both apps are independent. In the two prm's you have to define how the RAM will be used.

I need also handle the interrupt vector table. The bootloader will only use the reset vector. And I know that I can use the jump table support to redirect the addresses in interrupt vector table to this jump table, but what happens if we start to use expert mode programming when we add new code to the application how do we tell that this Interrupt addresses shall be placed in the jump table and not in the interrupt vector table.

Well, that depends on how you organize things. For example some monitors do just redirect the vectors while flashing, so the main app keeps the same layout as usual. Or your main app maps the vectors differently. With your vector table array below, just use the right address instead of 0xFFCC.

Do we need to handle this manually, how do we do that? Several people will write code so it may be dangerous if we need to manually edit the jump table.

Well, it does not differ from the normal setup, you also have one table for the complete app.

Today I use this method to handle IRQ. How do I Add the jump table here?

If you want, you can use the same setup.

At runtime the  app vector table will be at its own location, and not at 0xFFCC anymore.

void (* const _vect[])() @0xFFCC = {   /* Interrupt vector table */
         UNASSIGNED_ISR,               /* Int.no. 25 Vrti (at

Have a look how the serial monitor described in AN2140
implements the vector redirection. It's source code can be downloaded too (its written in assembly tough)

http://www.freescale.com/files/microcontrollers/doc/app_note/AN2140.pdf

Daniel

0 Kudos

386 Views
ajn
Contributor I
Hello Daniel,
 
Thanks for the help. I have split the application and the bootloader, and redirect the interrupt vectors, and it seems to work just fine now.
 
ajn
0 Kudos