BootLoader Interrupt vector for s08dz60

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

BootLoader Interrupt vector for s08dz60

3,008 Views
JaimeR
Contributor III

I am in the need of making a BootLoader using a S08DZ60. My problem is the following:

 I need my application to use an Interrupt vector 

 I need the bootloader to use an Interrupt vector (which can never be modified ) and I need my application to use an Interrupt vector (which can be modified).

 Any suggestion, example code or hint will be appreciatted.

Labels (1)
0 Kudos
8 Replies

1,209 Views
Punit
Contributor III

Jaime R did you find a way around to this issue?

I am also facing a similar issue and ISRs doesn't seems to work properly.

Can you share the result please?

0 Kudos

1,209 Views
tonyp
Senior Contributor II

Will something like this do?

 

Application Code

 

ISR

...

 rti

 

 org AppVector

 dw ISR

-------------------------------------

BootLoader Code

 

DoAppVector

 lda AppVector+1

 psha

 lda AppVector

 psha

 rts

 

 org FixedVector

 dw DoAppVector

 

Message Edited by tonyp on 2010-01-13 10:54 PM
0 Kudos

1,209 Views
JaimeR
Contributor III
hi tonyp, could you explan a little more since my assembly is not very good?
0 Kudos

1,209 Views
tonyp
Senior Contributor II

Each bootloader vector points to either ISR code in the bootloader (for those vectors that will never change), or to a subroutine that will redirect to the application ISR.  This will add an 18-cycle overhead to each ISR invocation.

 

The redirecting code simply loads the application vector from wherever you have decided to put those in your app memory  space (normally as a mirror stucture of the actual vectors but placed at the very end of your app code), puts it on stack, and jumps to it (via the RTS instruction, which is effectively a PULL PC instruction.)

 

Also, if your loader is written so that it automatically relocates actual vector contents to the app vector area, then writing your application would not require any special treatment, other than making sure code ends before the bootloader begins, even though vectors would still be located in their natural addresses.

0 Kudos

1,209 Views
JaimeR
Contributor III

Okay, now I have a better idea of what I need to do, I did a quick search in the forums and found the following code which seams well suited for my specific case.

 

void (* const _BOOT_vect[])() @0xFFC0 = {   /* Interrupt vector table */
         Bootload_ISR_31,                /* Int.no. 31 Vacmp2 (at F9C0)                Unassigned */
         Bootload_ISR_30,                /* Int.no. 30 Vacmp1 (at F9C2)                Unassigned */
       ...
         Bootload_ISR_02,                /* Int.no.  2 Virq (at F9FA)                  Unassigned */
         Bootload_ISR_01,                /* Int.no.  1 Vswi (at F9FC)                  Unassigned */
         Bootload_Main          /* Int.no.  0 Vreset (at F9FE)                Reset vector */
 };
 
where the functions are:

void Bootload_ISR_01(void) { asm ("LDX  $F9FC; PSHX; LDX  $F9FC; PSHX; RTS; ");};
void Bootload_ISR_02(void) { asm ("LDX  $F9FA; PSHX; LDX  $F9FA; PSHX; RTS; ");};
...
void Bootload_ISR_30(void) { asm ("LDX  $F9C2; PSHX; LDX  $F9C2; PSHX; RTS; ");};
void Bootload_ISR_31(void) { asm ("LDX  $F9FC; PSHX; LDX  $F9FC; PSHX; RTS; ");};

while the user application table is that created by P&E (relocated):

void (* const _vect[])() @0xF9C0 = {   /* Interrupt vector table */
         Cpu_Interrupt,                /* Int.no. 31 Vacmp2 (at F9C0)                Unassigned */
         Cpu_Interrupt,                /* Int.no. 30 Vacmp1 (at F9C2)                Unassigned */
       ...
         Cpu_Interrupt,                /* Int.no.  1 Vswi (at F9FC)                  Unassigned */
         _EntryPoint                   /* Int.no.  0 Vreset (at F9FE)                Reset vector */
 };

 

 

The interrupts will be taking the address to which to jump from a table located into application(not loader) code and therefore I will be in controll of which Interrupts will execute (either the bootloader interrupt or the application interrupts). Then my question will be the following 

 

How would I go back to loader mode if I am already running my application?, more specific, how can I know the address where the specific ISRs are located?

 

 

If someone has an example code about this and can share it, let me know, I will try to understand it even if its in assembly code.

 

Regards,

 

 

0 Kudos

1,209 Views
tonyp
Senior Contributor II

First of all, your sample code has errors.  All lines like this:

 

void Bootload_ISR_01(void) { asm ("LDX  $F9FC; PSHX; LDX  $F9FC; PSHX; RTS; ");};

 

should look like this:

 

void Bootload_ISR_01(void) { asm ("LDX  $F9FD; PSHX; LDX  $F9FC; PSHX; RTS; ");};

 

The first address is always plus one to get the second byte of the vector (which must be pushed first for RTS to work as expected -- big endian CPU).

 

Now, how to go back to loader mode?  What does that mean?  Normally, you wouldn't want to go back to loader mode unless you want to load new firmware.  So,

 

If you mean to run the loader again, you can force a reset (e.g., by means of illegal instruction.)

 

If you mean to run certain routines located in bootloader code, just call them (easier said than done in C, easier done than said in Assembly!)  If this code uses any non-stack memory (static etc), you'll have to take additional care so that no app variables overlap with bootloader variables (not what I'd recommend, just keep all RAM free for your app, unless you bootloader is actually a significant part of your application, e.g., an RTOS which certainly needs RAM for itself).

 

If you mean to go back to loader mode to upgrade the application, you can have a routine/function in your bootloader that will erase all non-protected Flash, and then reset the MCU.  Next run, the bootloader should see no code exists and stay in boot mode ready to load the new app.  It is assumed the bootloader always checks to see if valid code is present before starting the application (eg. CRC check) at every reset.

 

If you mean something else, what?

Message Edited by tonyp on 2010-01-14 09:14 PM
0 Kudos

1,209 Views
JaimeR
Contributor III

I am back again trying to make a bootloader. I still have problems with interrupt vector. This is the way I am doing it:

 

This is the bootloader ISR vector (not relocated).

 

 

void (* near const _vect[])() @0xFFC0 = {
         Bootload_ISR_00,                     
         Bootload_ISR_01,                     
         Bootload_ISR_02,                     
         Bootload_ISR_03,                     
         Bootload_ISR_04,               
         Bootload_ISR_05,               
         Bootload_ISR_06,               
         Bootload_ISR_07,               
         Bootload_ISR_08,                     
         Bootload_ISR_09,                     
         Bootload_ISR_10,                     
         Bootload_ISR_11,                     
         Bootload_ISR_12,                    
         Bootload_ISR_13,                     
         Bootload_ISR_14,                     
         Bootload_ISR_15,                     
         Bootload_ISR_16,                     
         Bootload_ISR_17,                     
         Bootload_ISR_18,                     
         Bootload_ISR_19,                     
         Bootload_ISR_20,                     
         Bootload_ISR_21,                     
         Bootload_ISR_22,                     
         Bootload_ISR_23,                     
         Bootload_ISR_24,                     
         Bootload_ISR_25,                     
         Bootload_ISR_26,                     
         Bootload_ISR_27,                     
         Bootload_ISR_28,                     
         Bootload_ISR_29,                     
         Bootload_ISR_30                      
};

void (* near const _vectReset[])() @0xFFFE = {
        _BootEntryPoint
};

 

This is how every Bootload_ISR_## function looks like(If it is signal to run loader, it runs loader ISR, if not it executes the ISR from the application

 

 

ISR(Bootload_ISR_03)
{
  dword ID;
  byte type, len,format;
  byte buff[8];
  int i;
 
   if(RunFromLoader){
      CAN1_ReadFrame(&ID,&type,&format,&len,buff);
      for(i = 0; i < 8 ; i++){
          CanMessage[i] =buff[i];
      }
      MssgReceived = TRUE;
      CANRFLG = CANRFLG_RXF_MASK;
   }
   else{
      asm {
        LDX  $1907
        PSHX
        LDX  $1906
        PSHX
        RTS       
      } 
   }
}

 

 

Now, in the part of the application code I am also NOT relocating the Interrupt Vector as I want my bootloader to ALWAYS decide wich routine to execute in order to serve an interrupt (application or loader). I am only defining a vector in address 0x1900 which looks like the following ( that is the reason the values above are $1905 and $1906 for ISR 03):

 

 

void (* near const _vect[])() @0x1900 = { /* Interrupt vector table */
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         CAN1_InterruptTx,            
         CAN1_InterruptRx,            
         CAN1_InterruptError,
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         SM1_Interrupt,               
         Buzzer_Interrupt,            
         Cpu_Interrupt,               
         TmDt1_Interrupt,             
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         Cpu_Interrupt,               
         _EntryPoint                  
};

 

The bootloader decides whether to run the loader or the application using the following:

 

 

    if(RunFromLoader)
        __asm   jmp _BootStartup ;
    else
        __asm   jmp 0x1941 ;

 

My application Interrupt Vector must end at 193F, and that is why I am jumping directly to 0x1941.

I have a couple of problems I have detected:

1.- When I add this code to my loader ISR 03 which corresponds to Receive CAN interrupt the loader failes as the first interrrupt arrives, even if that code is never executed. Its like if the addition of those 5 instructions exceeded the time or the code allowed for an interrupt. (Sounds wierd but it is what it looks like).

2.-Sometimes inverting the order of the ISR 03, for example :

 

ISR(Bootload_ISR_03){   if(!RunFromLoader){      asm {        LDX  $1907        PSHX        LDX  $1906        PSHX        RTS              }     }    else{       CAN1_ReadFrame(&ID,&type,&format,&len,buff);      for(i = 0; i < 8 ; i++){          CanMessage[i] =buff[i];      }            MssgReceived = TRUE;      CANRFLG = CANRFLG_RXF_MASK;      }}

 

instead of what I posted at the beggining (    RunFromLoader   ) and the if and else inverted. When I do that the loader works ( I dont whant to leave it like that because it seems like any small change in the code would make the loader fail) but the application still doesnt work even if the program is completely flash as the S19 file is. I believe the problem are the ISRs but I am speculating since I have no means of debugging because I can only debugg the bootloader which is not running anymore once the application is flashed.

Application is not the problem  because when I flash the application directly using BDM programmer it runs without any problem (I just have to place the vector at 0xFFC0 instead of 0x1900).

I am running out of ideas, does anyone knows something that I am not considering?, I will wait for any ideas.

This is the prm I am using for application and loader}:

 

 

LOADERSECTIONS    ROM                      =  READ_ONLY    0xEE00 TO 0xFFFF;    APPLICATION              =  READ_ONLY    0x1900 TO 0xEDFD;    EEPROM                   =  READ_ONLY    0x1400 TO 0x17FF;    RAM                      =  READ_WRITE   0x00A0 TO 0x107F;    Z_RAM                    =  READ_WRITE   0x0080 TO 0x009F; ENDAPPLICATIONSECTIONS    Z_RAM                    =  READ_WRITE   0x0080 TO 0x009F;    RAM                      =  READ_WRITE   0x00A0 TO 0x107F;    ROM                      =  READ_ONLY    0x1940 TO 0xEDFD;    EEPROM                   =  READ_ONLY    0x1400 TO 0x17FF;END

 

 

 

 

Regards,

 

 

 

 

 

 

 

 

 

0 Kudos

1,209 Views
CompilerGuru
NXP Employee
NXP Employee

The HLI code in the ISR assumes that the compiler is not saving any registers on the stack as directly jumps (with an RTS) to the interrupt handler of the app. Is there really nothing on the stack? I would check the disassembly. Especially look at the H register which is not stored by the CPU but by entry/exit code generated by the compiler. I would consider to write the ISR dispatcher code completely in HLI and move the actual C code into its own function (either a ISR as well called with a JMP or even a normal function, in which case the ISR code has to save H).

 

Daniel

0 Kudos