AnsweredAssumed Answered

Tips for making a multiple software image bootloader for MC9S12XEP100?

Question asked by utwig on Nov 15, 2013
Latest reply on Nov 27, 2013 by Edward Karpicz

Hi,

 

I have seen a lot of application notes and forum posts about bootloaders. But these are always about replacing the whole software on a microcontroller. On the contrary, I am trying to make a system with multiple software images and an ability to update just one of the images at a time.

 

My ultimate goal is to program a system with multiple, e.g. 4 redundant software images. When the system is started, the bootloader would run through a checksum operation on the first image to see if it is corrupted. If the image seems okay, image 1 execution would start. In case the image is corrupted, the same checksum chinspection would be done to the second image etc.

 

Another feature of this system would be the ability to perform an update to replace one of the software images with a new image. Currently my plan is to achieve this by putting the normal subroutines of each image to distinct P-Flash areas using pragmas e.g. #pragma CODE_SEG CODE_VER_A and  #pragma CODE_SEG CODE_VER_B etc. Segment CODE_VER_A would contain functions like A_function1(), A_function2()...  Segment CODE_VER_B would contain similar functions named B_function1(), B_function2().. My plan is to do something similar also with the XGATE code of each of the software images. The software update would be done with data coming in via an SCI module and stored  to a RAM or D-Flash buffer. This data would be used to overwrite the code segments of a software image not currently in use.

 

This approach causes some problems to arise from the Interrupt Service Routines. Each ISR can be directly defined only once in the source files. However, I want every image to have their own subroutines for handling the interrupts. My idea is to achieve this by redirecting each ISR to an image-specific interrupt handling subroutine, which passes the interrupt to a relevant subroutine for servicing the appropriate interrupt:

 

Example of an general ISR (all ISRs will have a similar structure):

#pragma CODE_SEG __NEAR_SEG NON_BANKED

interrupt VectorNumber_Vsci3 void SCI3_Receive(void) {

    switch(version){

        case 0x01:

        _A_IsrRedirect(VectorNumber_Vsci3);

        return;

        case 0x02:

        _B_IsrRedirect(VectorNumber_Vsci3);

        return;

        case 0x03:

        _C_IsrRedirect(VectorNumber_Vsci3);

        return;

        case 0x04:

        _C_IsrRedirect(VectorNumber_Vsci3);

        return;

    }

 

Image specific interrupt handling subroutine for image version "A":

#pragma CODE_SEG ISR_HNDLR_VER_A

void _A_IsrRedirect(unsigned char vec_num){

    switch(vec_num){

        case VectorNumber_1:

            _A_Service_1();

            break;

        case VectorNumber_2:

            _A_Service_2();

            break;

        case VectorNumber_Vsci3:

            _A_SCI3_Receive();

            break;

        //etc...   

    }

    //else

        //RESET!   

}


Example of an interrupt servicing subroutine in image version "A":

#pragma CODE_SEG CODE_VER_A

void _A_SCI3_Receive(void){

     //Enable further interrupts

     _asm CLI;

     //Clear the SCI3 XGATE interrupt flag

     XGIF_4F_40 = XGIF_4F_40_XGIF_44_MASK;

   

     //Enable SCI3 interrupt to start transmitting data

     SCI3CR2 |= SCI3CR2_TIE_MASK; 

}



Do you think that this is a viable approach to achieve what I am trying to do? Or do you have any ideas to make the implementation simpler? The point of having the intermediate image specific interrupt handling subroutine is to have only one interface between the ISRs (that cannot be updated) and each of the software images (A, B, C, D) interrupt handling subroutines.

 

Best Regards,

Timo

Outcomes