Bootloader for MC9S08DZ60

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

Bootloader for MC9S08DZ60

Jump to solution
2,476 Views
Michael71
Contributor II

Hi @ all,

 

I'm trying to implement a Bootloader on my MC9S08DZ60.

I have several questions but I didn't find any answers in the forums that match to my problem. So I am looking foreward to your replies.

 

1. is it possible to flash the bootloader in the protected section of ROM?

I want to make a application in C for the bootloader code which can flash a application program via CAN bus.

 

2. How is it possible to flash the user application to another ROM-Adress (unprotected)?

 

3. How can I jump from user application to bootloader and from bootloader to user application?

 

4. Can I flash two different programms with P&E micro USB Multilink interface? This is for testing the jumps between user application and bootloader. How should I do this? What files have to be adjusted?

 

5. Do you know other issues I have to take care about (Interrupt vector table relocation, .prm-file modifications)?

 

I use:

CodeWarrior 5.9.0

PE micro USB multilink interface

 

 

For the background informaton: The bootloader which I have to develop will be programmed to each ECU. The user application will be done seperately and should be flashed onto the controller via CAN-Bus. If an Reset occours the bootloader should start and chack, if there is a user application programmed. If so the bootloader should start the user application.

When the user application receives a special CAN-Message the bootloader should start agaín to erase the chip and flash a new user application.

When no user application is programmed on the chip the bootloader should run and wait for the user application to be flashed.

My idea is to programm a bootloader and locate it into a protected area of the Flash ROM with PE micro. When a user application is developed it should be possible to flash it into the unprotected area of Flash ROM also using PE micro but without overwriting the bootloader.

 

I read AN 2295 but I don't have experience with assembler code. The application will be programmed in C. 

 

 

Thank you very much for your help.

 

Regards

Michael

Labels (1)
1 Solution
1,208 Views
bigmac
Specialist III

Hello Michael,

 

I think that the problem is you are messing up your stack.  I notice that you are calling BOOT_ISR_11 (and all other ISRs) as a normal function, rather than as an interrupt function (with the interrupt keyword).  If you use the JMP form -

void BOOT_ISR_11( void)

{

   asm {

      ldhx  0xC3E8;    // Contains address of Timer1 function

      jmp  .x

   }

}

 

Here it is likely that the compiler will push the current values of the X and H registers onto the stack prior to the inline assembly code, and would restore these values prior to a normal RTS exit.  However, this function is never completed because the code does an indirect jump to the ISR code proper, which I will assume has the form -

interrupt void Timer1( void);

 

The use of the interrupt keyword means that the function will finish with an RTI instruction.  Here, the H register value will again be pushed onto the stack, and restored just prior to the RTI.  Can you see the problem?  There are more pushes than pulls, so the stack will be unbalanced, and the incorrect return address will be unstacked by the RTI.

 

However, also note that this method is appropriate for the reset vector redirection only, since _Startup should never exit, except by means of a reset.

 

Your attempt to then JSR to the interrupt function will always fail because of the RTI exit, and the unstacking differences between RTS and RTI.

 

An alternative is for BOOT_ISR_xx to use the interrupt keyword, and do an indirect JSR to the ISR code.

interrupt void BOOT_ISR_11( void)

{

   asm {

      ldhx  0xC3E8;    // Contains address of Timer1 function

      jsr  ,x

   }

}

 

The ISR code must therefore be a normal function, so that the function exit will be via BOOT_ISR_11, and what is placed on the stack during the process will be removed.

void Timer1( void);

 

Additionally, I assume that you are properly clearing the TPM1 overflow flag within the Timer1 function.

 

Regards,

Mac

 

View solution in original post

0 Kudos
12 Replies
1,208 Views
admin
Specialist II

1. is it possible to flash the bootloader in the protected section of ROM?

I want to make a application in C for the bootloader code which can flash a application program via CAN bus.

of course you can. and in my opnion, you have to. i have write a bootload in C and it works fine. you can use a .prm file to indicate where you want to locate your code.

 

2. How is it possible to flash the user application to another ROM-Adress (unprotected)?

 

first, you move your "flashing code"(i mean the code which carrys out the task of flash) into ram, and run it from ram. that is the most important thing for the bootloader.

 

3. How can I jump from user application to bootloader and from bootloader to user application?

 

my work is like this: the original reset vector points to the bootloader, and the relocated reset vector points to the application.  so when the CPU reset, it first enters the bootloader mode, and when it exits this mode, the SP load the relocated reset vector and RTS

 

4. Can I flash two different programms with P&E micro USB Multilink interface? This is for testing the jumps between user application and bootloader. How should I do this? What files have to be adjusted

 

i have not tried this method, however, i do not think this will work, unless these two programs are located in to different space in flash, and all this code are in only one SX or S19 file

 

5. Do you know other issues I have to take care about (Interrupt vector table relocation, .prm-file modifications)?

 

the dz60 support relocation of interrupt vector, you just need to define where it should go

 

My idea is to programm a bootloader and locate it into a protected area of the Flash ROM with PE micro. When a user application is developed it should be possible to flash it into the unprotected area of Flash ROM also using PE micro but without overwriting the bootloader.

 

i am not sure if you could do this. when i use a PE micro, it always ereases the entile flash. so i just debug the application, and download it into flash using the bootloader.

 

I read AN 2295 but I don't have experience with assembler code. The application will be programmed in C.

 

actually, i write my bootload almost in C, but in some cases, such as jumping from bootloader to application and reset, i still have to using inline asm.

 

hope you can understand my poor english.


0 Kudos
1,208 Views
bigmac
Specialist III

Hello Michael, and welcome to the forum.

 

1.  The bootloader code would occupy the upper reaches of flash, just below the interrupt vectiors, which would be write protected.  The flash below the bootloader can remain unprotected.  The erase of the unprotected flash will need to occur sector-by-sector, rather than a mass erase.

 

2.  During the erasing and programming of flash sectors, when high voltage is internally applied to a flash array, the flash cannot be read.  Conventionally, this means that a portion of the flash programming code must be located in RAM, either within the stack, or using a dedicated block of RAM for the purpose.  However, for the 'DZ60 device, the flash and the EEPROM blocks represent two different arrays, meaning that the code for erasing and programming the flash array may be alternatively located within the EEPROM array.  Within this forum (use the forum search engine), there are code samples for both the stack based method and the fixed RAM block method.  The latter code could potentially be adapted for the EEPROM location.

 

3.  A reset would cause entry to the bootloader code, which would determine that the user program was present and ready, and then jump to the start of the program, using a special vector location within the user code, whose address is known to the bootloader.  To return control to the bootloader would usually require a reset.  A reset may be generated by the user program, by making use of COP timeout, or generating an illegal opcode (ILOP) reset.  The latter is usually preferred because the reset will be immediate.

 

5.  Even though the device does support automatic vector redirection of all vectors except the reset vector (see paragraph 4.5.8 of the datasheet), you will not be able to make use of this feature should the bootloader itself require to use any interrupt.  In this case, you would need to provide code within the bootloader, for each interrupt, that effectively redirects via a vector table within the application, which is located at an address known to the bootloader.  For those interrupts used by the bootloader, the code would first need to determine that the bootloader had finished using the interrupt.

 

Some discussion of the bootloader controlled redirection process may be found here.  If using bootloader controlled redirection, the functions within the user code, for interrupt servicing, will likely need to be standard functions rather than the usual interrupt functions, i.e. not prefixed with the keyword "interrupt".  The reason for this is to maintain a balanced stack.

 

Regards,

Mac

 

0 Kudos
1,208 Views
Michael71
Contributor II

Hello Mac,

 

thank you for your reply. I'm trying to relocate the vectors within the bootloader code, because I need an interrupt to start a timer function. I used the assembler as stated in the recommended website but I also have a problem.

What I have done before:

I protected 15kb of flash and flashed the programm to the protected area.

Then I declared a interrupt vector table on Adress 0xC3FC. For the timer the interrupt 11 will be used and starts a function which I called Timer1 (void).

I left the NVOPT-Bit as 1.

The bootloader vector table looks like the following:

 

void (* near const BOOT_vect[])(void) @0xFFC0 = { /* Interrupt vector table */
         BOOT_ISR_31,                /* Int.no. 31 Vacmp2 (at FFC0)                Unassigned */
         BOOT_ISR_30,                /* Int.no. 30 Vacmp1 (at FFC2)                Unassigned */
         BOOT_ISR_29,                /* Int.no. 29 Vcantx (at FFC4)                Unassigned */
         BOOT_ISR_28,                /* Int.no. 28 Vcanrx (at FFC6)                Unassigned */
         BOOT_ISR_27,                /* Int.no. 27 Vcanerr (at FFC8)               Unassigned */
         BOOT_ISR_26,                /* Int.no. 26 Vcanwu (at FFCA)                Unassigned */
         BOOT_ISR_25,                /* Int.no. 25 Vrtc (at FFCC)                  Unassigned */
         BOOT_ISR_24,                /* Int.no. 24 Viic (at FFCE)                  Unassigned */
         BOOT_ISR_23,                /* Int.no. 23 Vadc (at FFD0)                  Unassigned */
         BOOT_ISR_22,                /* Int.no. 22 Vport (at FFD2)                 Unassigned */
         BOOT_ISR_21,                /* Int.no. 21 Vsci2tx (at FFD4)               Unassigned */
         BOOT_ISR_20,                /* Int.no. 20 Vsci2rx (at FFD6)               Unassigned */
         BOOT_ISR_19,                /* Int.no. 19 Vsci2err (at FFD8)              Unassigned */
         BOOT_ISR_18,                /* Int.no. 18 Vsci1tx (at FFDA)               Unassigned */
         BOOT_ISR_17,                /* Int.no. 17 Vsci1rx (at FFDC)               Unassigned */
         BOOT_ISR_16,                /* Int.no. 16 Vsci1err (at FFDE)              Unassigned */
         BOOT_ISR_15,                /* Int.no. 15 Vspi (at FFE0)                  Unassigned */
         BOOT_ISR_14,                /* Int.no. 14 Vtpm2ovf (at FFE2)              Unassigned */
         BOOT_ISR_13,                /* Int.no. 13 Vtpm2ch1 (at FFE4)              Unassigned */
         BOOT_ISR_12,                /* Int.no. 12 Vtpm2ch0 (at FFE6)              Unassigned */
         BOOT_ISR_11,                /* Int.no. 11 Vtpm1ovf (at FFE8)              Timer1*/
         BOOT_ISR_10,                /* Int.no. 10 Vtpm1ch5 (at FFEA)              Unassigned */
         BOOT_ISR_09,                /* Int.no.  9 Vtpm1ch4 (at FFEC)              Unassigned */
         BOOT_ISR_08,                /* Int.no.  8 Vtpm1ch3 (at FFEE)              Unassigned */
         BOOT_ISR_07,                /* Int.no.  7 Vtpm1ch2 (at FFF0)              Unassigned */
         BOOT_ISR_06,                /* Int.no.  6 Vtpm1ch1 (at FFF2)              Unassigned */
         BOOT_ISR_05,                /* Int.no.  5 Vtpm1ch0 (at FFF4)              Unassigned */
         BOOT_ISR_04,                /* Int.no.  4 Vlol (at FFF6)                  Unassigned */
         BOOT_ISR_03,                /* Int.no.  3 Vlvd (at FFF8)                  Unassigned */
         BOOT_ISR_02,                /* Int.no.  2 Virq (at FFFA)                  Unassigned */
         BOOT_ISR_01,                /* Int.no.  1 Vswi (at FFFC)                  Unassigned */
};

 

and the functions are:

 

void BOOT_ISR_01 (void)
{
  asm ("LDHX 0xC3FC; JMP ,X");
};

 

void BOOT_ISR_02 (void)
{
  asm
  ("LDHX 0xC3FA; JMP ,X");
};

 

...

 

void BOOT_ISR_11 (void)
{
  asm
  //("LDHX 0xC3E8; JMP, X")
  {
  ldhx #0xC3E8;
  ldhx ,X
  jsr ,X
  }
};

 

and so on.

 

0 Kudos
1,208 Views
Michael71
Contributor II

The interrupt vector table for servicing the Timer is (only modified in the address 0xC3C0, because I copied it from the first code whre it worked):

 

#ifndef UNASSIGNED_ISR
  #define UNASSIGNED_ISR ((void(*near const)(void)) 0xFFFF) /* unassigned interrupt service routine */
#endif

void (* near const _vect[])(void) @0xC3C0 = { /* Interrupt vector table */
         UNASSIGNED_ISR,               /* Int.no. 31 Vacmp2 (at FFC0)                Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 30 Vacmp1 (at FFC2)                Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 29 Vcantx (at FFC4)                Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 28 Vcanrx (at FFC6)                Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 27 Vcanerr (at FFC8)               Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 26 Vcanwu (at FFCA)                Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 25 Vrtc (at FFCC)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 24 Viic (at FFCE)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 23 Vadc (at FFD0)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 22 Vport (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 Vspi (at FFE0)                  Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 14 Vtpm2ovf (at FFE2)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 13 Vtpm2ch1 (at FFE4)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no. 12 Vtpm2ch0 (at FFE6)              Unassigned */
         Timer1,                   /* Int.no. 11 Vtpm1ovf (at FFE8)              Used */
         UNASSIGNED_ISR,               /* Int.no. 10 Vtpm1ch5 (at FFEA)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  9 Vtpm1ch4 (at FFEC)              Unassigned */
         UNASSIGNED_ISR,               /* Int.no.  8 Vtpm1ch3 (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 */
         UNASSIGNED_ISR,               /* Int.no.  4 Vlol (at FFF6)                  Unassigned */
         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 */
};

 

 

Now the problem is that the Function Timer1 is called for one time. After executing the Function the programm jumps back to Function BOOT_ISR_11 and then it the programm doesn't continue. It will remain in this BOOT_ISR_11.

 

Do I have to modify something to leave this Function?

 

Thank you in advance.

 

Regards

Michael

0 Kudos
1,209 Views
bigmac
Specialist III

Hello Michael,

 

I think that the problem is you are messing up your stack.  I notice that you are calling BOOT_ISR_11 (and all other ISRs) as a normal function, rather than as an interrupt function (with the interrupt keyword).  If you use the JMP form -

void BOOT_ISR_11( void)

{

   asm {

      ldhx  0xC3E8;    // Contains address of Timer1 function

      jmp  .x

   }

}

 

Here it is likely that the compiler will push the current values of the X and H registers onto the stack prior to the inline assembly code, and would restore these values prior to a normal RTS exit.  However, this function is never completed because the code does an indirect jump to the ISR code proper, which I will assume has the form -

interrupt void Timer1( void);

 

The use of the interrupt keyword means that the function will finish with an RTI instruction.  Here, the H register value will again be pushed onto the stack, and restored just prior to the RTI.  Can you see the problem?  There are more pushes than pulls, so the stack will be unbalanced, and the incorrect return address will be unstacked by the RTI.

 

However, also note that this method is appropriate for the reset vector redirection only, since _Startup should never exit, except by means of a reset.

 

Your attempt to then JSR to the interrupt function will always fail because of the RTI exit, and the unstacking differences between RTS and RTI.

 

An alternative is for BOOT_ISR_xx to use the interrupt keyword, and do an indirect JSR to the ISR code.

interrupt void BOOT_ISR_11( void)

{

   asm {

      ldhx  0xC3E8;    // Contains address of Timer1 function

      jsr  ,x

   }

}

 

The ISR code must therefore be a normal function, so that the function exit will be via BOOT_ISR_11, and what is placed on the stack during the process will be removed.

void Timer1( void);

 

Additionally, I assume that you are properly clearing the TPM1 overflow flag within the Timer1 function.

 

Regards,

Mac

 

0 Kudos
1,208 Views
Michael71
Contributor II

Hello Mac,

 

thank you very much for your reply and the very good explanation of things that will happen. I forgot to add keyword "interrupt" to my Function Timer1. After that it is workin properly.

 

Just two questions:

I'm a little bit confused about the vector relocation. What I understood is that if an area of ROM is protected the vector table is protected. And therefore it must be relocated i.e. to 0xC3C0. In the vector table at address 0xC3C0 there are the interrupt fuctions i.e. Timer1 which is used by the bootloader and will be used by the application which has to flashed later. As far as I understood the assembly code fetches the content of the address at 0xC3C0 and carries out the ISR. Did I understand this right and if so, why couldn't I use the interrupt table at 0xC3C0? I saw in the first reply that I need to determine that the bootloader had finished to use this interrupt. This I don't understand, because I thought, when the user programm starts the bootloader has finished his work, and doesn't need any interrupt no more.

If it is possible, please explain this to me, because I'm a real Newbie.

 

My second question is: From your point of view and experience with bootloader would it be better to use

void BOOT_ISR_xx ( void) or interrupt void BOOT_ISR_xx ( void)? Because I saw in the recommended discussen that you suggest interrupt void BOOT_ISR_xx ( void) and to declare the functions for interrupt servicing as normal functions. What would be the better solution (if there is a better solution)?

 

Thank you in advance.

Thank also to ToBeNoOne for his useful hints!

 

 

Now I will try to copy the functions for erasing and programming into RAM.

 

Regards

Michael

0 Kudos
1,208 Views
bigmac
Specialist III

Hello Michael,

 

If you had enabled automatic vector redirection, and with the application vector table commencing at an address of 0xC3C0, it would be implicit that addresses of 0xC400 and above are write protected, i.e. the boot loader code commences at 0xC400  (which seems a rather large bootloader).  With automatic redirection, the application vector table is used directly by the MCU, and the normal vector locations are ignored (except for the reset vector).

 

However, automatic redirection cannot be used, since you require one or more interrupts to be used within the bootloader, and the vector redirection to the application program must be controlled by the bootloader.  I suggest that you use the same redirection rules as automatic redirection.

 

So the vector for interrupt number 11 will remain situated at 0xFFE8, and this will contain the address of the furnction BOOT_ISR_11().  The code within this function must then determine whether the bootloader or the application code is currently running.  If the bootloader is still running, the bootloader ISR would be executed.  However, if the application code is running, the function code will read the contents of the redirected vector at address 0xC3E8 (within the vector table for the application).  The word value read will be the address of the application ISR for this interrupt.

 

You must use:

interrupt void BOOT_ISR_xx( void);

This is so the compiler will place the current h-register value to the stack (because this is not automatically stacked by the interrupt process), and will restore the register value on exit.  I then suggested that the application ISR function be a normal function (that terminates with RTS), which is entered by means of the JSR  ,X instruction.

 

If you were to use the form:

interrupt void Timer1( void);

the following changes would be necessary.  Since this function terminates with RTI, it cannot be called using JSR, so JMP must be used within BOOT_ISR_11().  Secondly, the h-register value will again be pushed to the stack,  so the function Timer1() would need to discard the stored value in order for the function to correctly terminate.  This second requirement is very risky, since the code would fail if it used as a non-redirected ISR, and the reason would not be obvious.

 

The ISR code as a standard function would also fail in this respect, but the reason should be evident from the function prototype.

 

Regards,

Mac

 

0 Kudos
1,208 Views
Michael71
Contributor II

Hello Mac,

 

than you very much for your explanation.

So I will change the Functions

void BOOT_ISR_XX ( void) to interrupt void BOOT_ISR_XX ( void).

 

Just to avoid making another mistake:

In my bootloader (which is really large, because I estimated the space which the bootloader will need to test this vector redirection) I will have the vector table:

void (* near const BOOT_vect[])(void) @0xFFC0... with the Functions:

interrupt void BOOT_ISR_XX ( void)

where the Functions interrupt void BOOT_ISR_XX ( void) only contain:

asm 
  {
  ldhx #0xC3E8;
  ldhx ,X
  jsr ,X
  }

 

And then I have a second vector Table in my bootloader code:

void (* near const _vect[])(void) @0xC3C0... with the Functions:

Timer1.

 

In the application code later I will only have one vector table pointing to

void (* near const _vect[])(void) @0xC3C0... with the Functions:

Timer1?

Or must I use

void (* near const BOOT_vect[])(void) @0xFFC0... with the functions:

interrupt void BOOT_ISR_XX ( void)?

 

As far as I understood the vector redirection: The interrupt vector table is still located at it's default place at 0xFFC0. The bootloader fetches the address of of TIMER1 from the second vector table which is equal to to the vector table in the later application, and will execute the TIMER1 as a standard function without the Keyword "interrupt".

 

The application code must use the vector table at 0xC3C0? And in the application code the function TIMER1 is an interrupt function containing the keyword "interrupt"?

Did I understand that right or do I have to implement something to my interrupt BOOT_ISR_XX functions to determine whether the Bootloader or the application is running?

I understood the whole time, that the redirection is also necessary when the regular user application has started. But now I'm thinking, that the vector redirection is only necessary, when the bootloader is active. Is that right?


bigmac wrote:

However, automatic redirection cannot be used, since you require one or more interrupts to be used within the bootloader, and the vector redirection to the application program must be controlled by the bootloader.  I suggest that you use the same redirection rules as automatic redirection.

 


 

My problem is that I have no experience with this redirection rules. I took the code examples and put to my bootloader hoping that everything will wok properly. It is my first project programming a mcu. That is the reason why I have to ask this (maybe very simple) questions.

 

Thank you again in advance.

 

Best Regards

Michael

0 Kudos
1,208 Views
bigmac
Specialist III

Hello Michael,

 

If your bootloader commences at address 0xC400, the application vector table, starting at address 0xC3C0, is obviously not part of the bootloader.  The "redirection rule" that I was referring was simply that the application vector table should be located within the highest unprotected flash sector, as is currently the case with the above addresses.

 

When BOOT_ISR_11() is entered as the result of TPM overflow, the interrupt code will determine what is the current operating mode only as a result of reading the state of a global flag that is controlled by the bootloader.

 

interrupt void BOOT_ISR_11( void){   if (user_flag) {     // User mode is current      __asm {         ldhx  0xC3E8;  // User vector         jsr   ,x      }   }   else {               // Bootloader mode      // Bootloader ISR code here      }}

I would be of the personal opinion that the design of a bootloader is too advanced as a first project.

 

Regards,

Mac

 

0 Kudos
1,208 Views
Michael71
Contributor II

Hello Mac,

 

thank you for your answer and your kind support. I really apprciate it! :smileyhappy:

 

I understood the problem a little bit now and I will use the code example in your last post.

 

I agree with you that this project is really hard but I learned a lot in the past few weeks. I did not know what problems will occur and I never thought of such a problem like interrupt vector redirection. And the next problem I face currently is to run a portion of code out of RAM. I found something in this forum and now I will use it in my bootloader... I think this will be my next thread.

As I choose this project to do I informed me outside of the freescale forums, because currently we use Atmel controllers. For Atmel controllers it seemed to me that a bootloader is makeable and some Controllers have a bootloader support implemented.

 

But I will go ahaed to bring the project to an successful end...

 

Best Regards

Michael

0 Kudos
1,208 Views
Michael71
Contributor II

Hi,

 

thank you very much for your help:smileyhappy:. I will try out step by step.

 

 

Michael

0 Kudos
1,208 Views
Michael71
Contributor II
Hello,

Could no one help me with my questions? Any hint would be helpful.

Thanks
Michael
0 Kudos