EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Force the reset vector to a specific address

Started by Robert April 6, 2010
This scheme seems a little backwards to me but then again I am not
privy to all of the design decisions.

Presumably you will use the bootloader as a means to update the
application code in the device. This will involve erasing the
application flash sectors, including the interrupt and reset vector,
before reloading with the new code. The bootloader sectors are
"protected" and not erased so the bootloader can keep running. If
there is a power or comms failure during the reload process there is a
probability that you will be left with a device that has no data in
the reset vector and hence a bricked unit. (Been there, got the
T-shirt)

A better method is to have a bootloader that includes the reset vector
and then to have a secondary reset/interrupt vector in the application
code. When a reset occurs the bootloader runs as much initialisation
as you want before using the application vector table to find the
start address of the application. For the interrupts, each vector
entry in the processor vector table points to an instruction to jump
to an address taken from the application interrupt vector table. OK,
one extra instruction on the front of every interrupt function but
this should not be a killer - If it is then you have other problems!

Ian

On 15 April 2010 06:15, Robert wrote:
> Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
>
> With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
>
> Thanks.
>
> --- In m..., "josephleeinus" wrote:
>> I would do it in this way:
>>
>> //Flash a const to 0xFFFE-0xFFFF
>> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
>>
>> and custom the linker command file
>> -Z(CODE)INTVEC7E-FFFE (not override the reset vector)
>> -Z(CODE)RESETC-F7FD (/*someother place*/)
>>
>> --- In m..., "Robert" wrote:
>> >
>> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
>> >
>> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
>> >
>> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
>> >
>> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
>> >
>>
>

Beginning Microcontrollers with the MSP430

We took an approach very similar to what you described, with one notable exception. We just didn't use interrupts in the bootloader! So, fine, the bootloader code is not quite as elegant as it could be (lots of spinning in loops, no lower modes, etc.) but it was a good trade off for us as the bootloader normally only runs for a few seconds at startup. In fact, in our application, the software may run for years uninterrupted as it is an implantable device, so a few seconds of inefficiency was well worth while for a nice application (where one extra cycle on an interrupt did sort of matter).

Someone (eh hem, TI, we know you're reading...) should write a white paper summarizing all these options and best practices. There are lots of tricks that people know, and a lot of wheel re-inventing. Topics include:
+Custom boot loaders
+Multiple applications in the same flash
+Re-directing interrupt vectors (i.e. "the one jump hit")
+Robust firmware upgrading with custom bootloader

Stuart
--- In m..., Ian Okey wrote:
>
> This scheme seems a little backwards to me but then again I am not
> privy to all of the design decisions.
>
> Presumably you will use the bootloader as a means to update the
> application code in the device. This will involve erasing the
> application flash sectors, including the interrupt and reset vector,
> before reloading with the new code. The bootloader sectors are
> "protected" and not erased so the bootloader can keep running. If
> there is a power or comms failure during the reload process there is a
> probability that you will be left with a device that has no data in
> the reset vector and hence a bricked unit. (Been there, got the
> T-shirt)
>
> A better method is to have a bootloader that includes the reset vector
> and then to have a secondary reset/interrupt vector in the application
> code. When a reset occurs the bootloader runs as much initialisation
> as you want before using the application vector table to find the
> start address of the application. For the interrupts, each vector
> entry in the processor vector table points to an instruction to jump
> to an address taken from the application interrupt vector table. OK,
> one extra instruction on the front of every interrupt function but
> this should not be a killer - If it is then you have other problems!
>
> Ian
>
> On 15 April 2010 06:15, Robert wrote:
> > Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
> >
> > With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
> >
> > Thanks.
> >
> > --- In m..., "josephleeinus" wrote:
> >>
> >>
> >> I would do it in this way:
> >>
> >> //Flash a const to 0xFFFE-0xFFFF
> >> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
> >>
> >> and custom the linker command file
> >> -Z(CODE)INTVEC7E-FFFE (not override the reset vector)
> >> -Z(CODE)RESETC-F7FD (/*someother place*/)
> >>
> >> --- In m..., "Robert" wrote:
> >> >
> >> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
> >> >
> >> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
> >> >
> >> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
> >> >
> >> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
> >> >
> >>
> >
> >
> >
> >
> >
> >
> >
> >
> >
AMEN, Stuart!!!

Mike Raines

________________________________
From: m... [mailto:m...] On Behalf Of Stuart_Rubin
Sent: Thursday, April 15, 2010 9:24 AM
To: m...
Subject: [SPAM] [msp430] Re: Force the reset vector to a specific address
Importance: Low

We took an approach very similar to what you described, with one notable exception. We just didn't use interrupts in the bootloader! So, fine, the bootloader code is not quite as elegant as it could be (lots of spinning in loops, no lower modes, etc.) but it was a good trade off for us as the bootloader normally only runs for a few seconds at startup. In fact, in our application, the software may run for years uninterrupted as it is an implantable device, so a few seconds of inefficiency was well worth while for a nice application (where one extra cycle on an interrupt did sort of matter).

Someone (eh hem, TI, we know you're reading...) should write a white paper summarizing all these options and best practices. There are lots of tricks that people know, and a lot of wheel re-inventing. Topics include:
+Custom boot loaders
+Multiple applications in the same flash
+Re-directing interrupt vectors (i.e. "the one jump hit")
+Robust firmware upgrading with custom bootloader

Stuart
--- In m..., Ian Okey wrote:
>
> This scheme seems a little backwards to me but then again I am not
> privy to all of the design decisions.
>
> Presumably you will use the bootloader as a means to update the
> application code in the device. This will involve erasing the
> application flash sectors, including the interrupt and reset vector,
> before reloading with the new code. The bootloader sectors are
> "protected" and not erased so the bootloader can keep running. If
> there is a power or comms failure during the reload process there is a
> probability that you will be left with a device that has no data in
> the reset vector and hence a bricked unit. (Been there, got the
> T-shirt)
>
> A better method is to have a bootloader that includes the reset vector
> and then to have a secondary reset/interrupt vector in the application
> code. When a reset occurs the bootloader runs as much initialisation
> as you want before using the application vector table to find the
> start address of the application. For the interrupts, each vector
> entry in the processor vector table points to an instruction to jump
> to an address taken from the application interrupt vector table. OK,
> one extra instruction on the front of every interrupt function but
> this should not be a killer - If it is then you have other problems!
>
> Ian
>
> On 15 April 2010 06:15, Robert wrote:
> > Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
> >
> > With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
> >
> > Thanks.
> >
> > --- In m..., "josephleeinus" wrote:
> >>
> >>
> >> I would do it in this way:
> >>
> >> //Flash a const to 0xFFFE-0xFFFF
> >> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
> >>
> >> and custom the linker command file
> >> -Z(CODE)INTVEC7E-FFFE (not override the reset vector)
> >> -Z(CODE)RESETC-F7FD (/*someother place*/)
> >>
> >> --- In m..., "Robert" wrote:
> >> >
> >> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
> >> >
> >> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
> >> >
> >> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
> >> >
> >> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
> >> >
> >>
> >
> >
> >
> >
> >
> >
> >
> >
> >
At first, I thought not using interrupts in the bootloader was restrictive too, but when I thought about it, the bootloader was only doing one thing at a time. It was either:

1. Waiting for serial input.
2. Acting on received input
a) Erasing a flash segment
b) Programming flash
3. Sending a response

None of these tasks overlapped, so polling was really quite acceptable.

The question with forcing the reset vector was to accommodate that one area that both the application and bootloader overlapped; them both trying to specify their start address in the reset vector. If I could get the bootloader to stop "clobbering" the application reset vector, then I could build both, and program them both, w/o having to edit the output files.

--- In m..., Mike Raines wrote:
>
> AMEN, Stuart!!!
>
> Mike Raines
>
> ________________________________
> From: m... [mailto:m...] On Behalf Of Stuart_Rubin
> Sent: Thursday, April 15, 2010 9:24 AM
> To: m...
> Subject: [SPAM] [msp430] Re: Force the reset vector to a specific address
> Importance: Low
>
> We took an approach very similar to what you described, with one notable exception. We just didn't use interrupts in the bootloader! So, fine, the bootloader code is not quite as elegant as it could be (lots of spinning in loops, no lower modes, etc.) but it was a good trade off for us as the bootloader normally only runs for a few seconds at startup. In fact, in our application, the software may run for years uninterrupted as it is an implantable device, so a few seconds of inefficiency was well worth while for a nice application (where one extra cycle on an interrupt did sort of matter).
>
> Someone (eh hem, TI, we know you're reading...) should write a white paper summarizing all these options and best practices. There are lots of tricks that people know, and a lot of wheel re-inventing. Topics include:
> +Custom boot loaders
> +Multiple applications in the same flash
> +Re-directing interrupt vectors (i.e. "the one jump hit")
> +Robust firmware upgrading with custom bootloader
>
> Stuart
> --- In m..., Ian Okey wrote:
> >
> > This scheme seems a little backwards to me but then again I am not
> > privy to all of the design decisions.
> >
> > Presumably you will use the bootloader as a means to update the
> > application code in the device. This will involve erasing the
> > application flash sectors, including the interrupt and reset vector,
> > before reloading with the new code. The bootloader sectors are
> > "protected" and not erased so the bootloader can keep running. If
> > there is a power or comms failure during the reload process there is a
> > probability that you will be left with a device that has no data in
> > the reset vector and hence a bricked unit. (Been there, got the
> > T-shirt)
> >
> > A better method is to have a bootloader that includes the reset vector
> > and then to have a secondary reset/interrupt vector in the application
> > code. When a reset occurs the bootloader runs as much initialisation
> > as you want before using the application vector table to find the
> > start address of the application. For the interrupts, each vector
> > entry in the processor vector table points to an instruction to jump
> > to an address taken from the application interrupt vector table. OK,
> > one extra instruction on the front of every interrupt function but
> > this should not be a killer - If it is then you have other problems!
> >
> > Ian
> >
> > On 15 April 2010 06:15, Robert wrote:
> > > Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
> > >
> > > With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
> > >
> > > Thanks.
> > >
> > > --- In m..., "josephleeinus" wrote:
> > >>
> > >>
> > >> I would do it in this way:
> > >>
> > >> //Flash a const to 0xFFFE-0xFFFF
> > >> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
> > >>
> > >> and custom the linker command file
> > >> -Z(CODE)INTVEC7E-FFFE (not override the reset vector)
> > >> -Z(CODE)RESETC-F7FD (/*someother place*/)
> > >>
> > >> --- In m..., "Robert" wrote:
> > >> >
> > >> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
> > >> >
> > >> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
> > >> >
> > >> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
> > >> >
> > >> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
> > >> >
> > >>
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
You're absolutely correct Ian, it is backwards. The application was written first as a stand-alone build. Later, the idea of being able to update the application was added, and the bootloader was created. The bootloader should really be called first, verify a checksum in the application area, and launch it if valid. That kind of retrofitting was not done.

We will certainly brick the device if the programming fails. I don't like it. I keep thinking I should push to change this, but I don't think they'll agree if they have to pay for it. Maybe I should've pushed for this design change in the beginning, but alas.

--- In m..., Ian Okey wrote:
>
> This scheme seems a little backwards to me but then again I am not
> privy to all of the design decisions.
>
> Presumably you will use the bootloader as a means to update the
> application code in the device. This will involve erasing the
> application flash sectors, including the interrupt and reset vector,
> before reloading with the new code. The bootloader sectors are
> "protected" and not erased so the bootloader can keep running. If
> there is a power or comms failure during the reload process there is a
> probability that you will be left with a device that has no data in
> the reset vector and hence a bricked unit. (Been there, got the
> T-shirt)
>
> A better method is to have a bootloader that includes the reset vector
> and then to have a secondary reset/interrupt vector in the application
> code. When a reset occurs the bootloader runs as much initialisation
> as you want before using the application vector table to find the
> start address of the application. For the interrupts, each vector
> entry in the processor vector table points to an instruction to jump
> to an address taken from the application interrupt vector table. OK,
> one extra instruction on the front of every interrupt function but
> this should not be a killer - If it is then you have other problems!
>
> Ian
>
> On 15 April 2010 06:15, Robert wrote:
> > Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
> >
> > With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
> >
> > Thanks.
> >
> > --- In m..., "josephleeinus" wrote:
> >>
> >>
> >> I would do it in this way:
> >>
> >> //Flash a const to 0xFFFE-0xFFFF
> >> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
> >>
> >> and custom the linker command file
> >> -Z(CODE)INTVEC7E-FFFE (not override the reset vector)
> >> -Z(CODE)RESETC-F7FD (/*someother place*/)
> >>
> >> --- In m..., "Robert" wrote:
> >> >
> >> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
> >> >
> >> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
> >> >
> >> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
> >> >
> >> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
> >> >
> >>
> >
> >
> >
> >
> >
> >
> >
> >
> >
As I said, I have the T-shirt. It really was not very difficult to do
the change. Going from one mode to the other just involved an extra
load stage to replace the application with the new bootloader and then
load the application using the new loader. The deciding factor was
when one of our directors made his own serial cable with very bad
solder joints and bricked a unit in front of a customer. Kind of
concentrates the mind ;-)

Ian

On 15 April 2010 21:55, Robert wrote:
> You're absolutely correct Ian, it is backwards. The application was written first as a stand-alone build. Later, the idea of being able to update the application was added, and the bootloader was created. The bootloader should really be called first, verify a checksum in the application area, and launch it if valid. That kind of retrofitting was not done.
>
> We will certainly brick the device if the programming fails. I don't like it. I keep thinking I should push to change this, but I don't think they'll agree if they have to pay for it. Maybe I should've pushed for this design change in the beginning, but alas.
>
> --- In m..., Ian Okey wrote:
>>
>> This scheme seems a little backwards to me but then again I am not
>> privy to all of the design decisions.
>>
>> Presumably you will use the bootloader as a means to update the
>> application code in the device. This will involve erasing the
>> application flash sectors, including the interrupt and reset vector,
>> before reloading with the new code. The bootloader sectors are
>> "protected" and not erased so the bootloader can keep running. If
>> there is a power or comms failure during the reload process there is a
>> probability that you will be left with a device that has no data in
>> the reset vector and hence a bricked unit. (Been there, got the
>> T-shirt)
>>
>> A better method is to have a bootloader that includes the reset vector
>> and then to have a secondary reset/interrupt vector in the application
>> code. When a reset occurs the bootloader runs as much initialisation
>> as you want before using the application vector table to find the
>> start address of the application. For the interrupts, each vector
>> entry in the processor vector table points to an instruction to jump
>> to an address taken from the application interrupt vector table. OK,
>> one extra instruction on the front of every interrupt function but
>> this should not be a killer - If it is then you have other problems!
>>
>> Ian
>>
>> On 15 April 2010 06:15, Robert wrote:
>> > Interesting. Just to recap, I'm trying to put two separate builds in the same memory space. I want the application to use the reset vector, and I want the bootloader to not use the reset vector, since it will get called by the application.
>> >
>> > With this method, I can redefine the reset vector address for the bootloader to be someplace in the bootloader flash area, so that it won't mess with the actual reset vector. Of course, it won't execute until the application calls it, but that's how it's designed.
>> >
>> > Thanks.
>> >
>> > --- In m..., "josephleeinus" wrote:
>> >>
>> >>
>> >> I would do it in this way:
>> >>
>> >> //Flash a const to 0xFFFE-0xFFFF
>> >> static const uint16 entry_point @ 0xFFFE = ENTRY_POINT_ADDR
>> >>
>> >> and custom the linker command file
>> >> -Z(CODE)INTVEC=FF7E-FFFE (not override the reset vector)
>> >> -Z(CODE)RESET=F7FC-F7FD (/*someother place*/)
>> >>
>> >> --- In m..., "Robert" wrote:
>> >> >
>> >> > Hello. I saw this question asked a little while back but I didn't see anyone answer this specific question. Here's the situation. We have a custom bootloader and an application. In IAR, both builds set the reset vector to the start of that build. The location in memory is changed specified in the linker file.
>> >> >
>> >> > The interrupt vectors are used by the application only, except for that pesky reset vector. Our current process is to program the bootloader first, and then the app, so the reset vector for the app is valid. In reality, our "bootloader" is just a reprogrammer. It's not called at boot-up.
>> >> >
>> >> > We want to change this so the bootloader is called at boot-up. That way, if the app is invalid, the bootloader will wait for data on the serial port to reprogram the app. So, I want the application to set the reset vector to a specific address for where the bootloader is located, and to "ignore" its own reset address.
>> >> >
>> >> > I could write some sort of command line tool that does this, and call it as a post-build action for the application, but this seems too difficult. Can I "force" the linker set a value in flash, and not have it overwritten by the reset vector? Any thoughts?
>> >> >
>> >>
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >
>> >

Memfault Beyond the Launch