EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Share code between bootloader and application

Started by pozz June 7, 2016
I will use one MCU with integrated USB OTG peripheral for two purposes:

- bootloader for firmware upgrade from USB pendrive
- USB connection to an Android smartphone during application

As you know, USB Host stack is a complex piece of code that has a high 
Flash size.
In my scenario, I need two different USB Host: one for bootloader and 
one for application.

Is there a possibility to share the USB Host stack between bootloader 
and application in some way?

Most probably, I'll use a Cortex-Mx MCU with gcc toolchain.
On 07/06/16 20:49, pozz wrote:
> I will use one MCU with integrated USB OTG peripheral for two purposes: > > - bootloader for firmware upgrade from USB pendrive > - USB connection to an Android smartphone during application > > As you know, USB Host stack is a complex piece of code that has a high > Flash size. > In my scenario, I need two different USB Host: one for bootloader and > one for application. > > Is there a possibility to share the USB Host stack between bootloader > and application in some way? > > Most probably, I'll use a Cortex-Mx MCU with gcc toolchain.
Overlay linkers used to do this kind of thing, but really the right answer now is to create a jump table or a C++ object that implements a virtual interface, and expose it from the bootloader. Then in the application code all you need is a single pointer. Essentially it becomes your USB Host BIOS. You just need to ensure that any and all library code that gets dragged in is appropriate to both environments, for example, any memory that gets allocated in the bootloader gets freed there too, not by a free() in the app code. Clifford Heath.
On 2016-06-07, pozz <pozzugno@gmail.com> wrote:

> Is there a possibility to share the USB Host stack between bootloader > and application in some way?
Yes. -- Grant Edwards grant.b.edwards Yow! MY income is ALL at disposable! gmail.com
On Tuesday, June 7, 2016 at 6:49:16 AM UTC-4, pozz wrote:
> ...Is there a possibility to share the USB Host stack between bootloader > and application in some way?
Sure, however, normally boot-loader and application assume that they own everything, and you must ensure no conflicts, by: 1) fix and reserve any static RAM required for the shared code (USB Host and file system) 2) make sure IRQ routing to the USB stack is consistent 3) publish the addresses of anything public in bootloader as an API at a fixed address (table of entry points to functions and ISRs) 4) ensure there is no conflict between C/C++ RTL used in shared code and your application Avoid dynamic memory in shared code! Reserve and fix memory required for entry point table and dedicated RAM in your linker scripts, and you're all set. Hope that helps! Best Regards, Dave
On 6/7/2016 3:49 AM, pozz wrote:
> I will use one MCU with integrated USB OTG peripheral for two purposes: > > - bootloader for firmware upgrade from USB pendrive > - USB connection to an Android smartphone during application > > As you know, USB Host stack is a complex piece of code that has a high Flash size. > In my scenario, I need two different USB Host: one for bootloader and one for > application. > > Is there a possibility to share the USB Host stack between bootloader and > application in some way? > > Most probably, I'll use a Cortex-Mx MCU with gcc toolchain.
That depends on the capabilities that you require in each "instance" of the stack. Also, on the environment in which you expect each instance to operate! It's usually easier to write a piece of code to rely on MORE facilities (than less). Typically, boot loaders want to be as "slim" as possible. This helps ensure they are "correct" (no latent bugs that will cause your boot loader to misperform at a later date -- leaving you "stuck"). It also tends to make it easier to "step away" from the boot loader after the image has been pulled in -- less scaffolding to tear down as you transition to "application mode" (e.g., did you remember to disable any services upon which the loader relied that might conflict with services in the application's run-time?)
On Tue, 07 Jun 2016 06:43:04 -0700, Don Y wrote:

> On 6/7/2016 3:49 AM, pozz wrote: >> I will use one MCU with integrated USB OTG peripheral for two purposes: >> >> - bootloader for firmware upgrade from USB pendrive - USB connection to >> an Android smartphone during application >> >> As you know, USB Host stack is a complex piece of code that has a high >> Flash size. >> In my scenario, I need two different USB Host: one for bootloader and >> one for application. >> >> Is there a possibility to share the USB Host stack between bootloader >> and application in some way? >> >> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. > > That depends on the capabilities that you require in each "instance" of > the stack. Also, on the environment in which you expect each instance > to operate! It's usually easier to write a piece of code to rely on > MORE facilities (than less). > > Typically, boot loaders want to be as "slim" as possible. This helps > ensure they are "correct" (no latent bugs that will cause your boot > loader to misperform at a later date -- leaving you "stuck"). It also > tends to make it easier to "step away" from the boot loader after the > image has been pulled in -- less scaffolding to tear down as you > transition to "application mode" (e.g., did you remember to disable any > services upon which the loader relied that might conflict with services > in the application's run-time?)
If he needs to read USB drives from the bootloader, he's already crossed the Rubicon as far as code complexity goes. Beyond that he just needs to control risks. I might implement a bootloader for the bootloader, for when things REALLY mess up. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com I'm looking for work -- see my website!
On Tue, 07 Jun 2016 21:15:13 +1000, Clifford Heath wrote:

> On 07/06/16 20:49, pozz wrote: >> I will use one MCU with integrated USB OTG peripheral for two purposes: >> >> - bootloader for firmware upgrade from USB pendrive - USB connection to >> an Android smartphone during application >> >> As you know, USB Host stack is a complex piece of code that has a high >> Flash size. >> In my scenario, I need two different USB Host: one for bootloader and >> one for application. >> >> Is there a possibility to share the USB Host stack between bootloader >> and application in some way? >> >> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. > > Overlay linkers used to do this kind of thing, but really the right > answer now is to create a jump table or a C++ object that implements a > virtual interface, and expose it from the bootloader. Then in the > application code all you need is a single pointer. Essentially it > becomes your USB Host BIOS. > > You just need to ensure that any and all library code that gets dragged > in is appropriate to both environments, for example, any memory that > gets allocated in the bootloader gets freed there too, not by a free() > in the app code. > > Clifford Heath.
What everyone has said so far, plus: I'm going to go ahead and call it a BIOS here, because that's basically what you're doing. Whatever you do you need to make sure to make the API between BIOS and application code as consistent as possible. So -- a jump table, or a single address that gets called with parameters, or possibly a guaranteed- unused interrupt that you hijack to branch to the BIOS. What you absolutely positively don't want to do is to just link the boot code, then link the application code against the boot code's 'native' addresses -- that will pretty much guarantee that each application version will be firmly tied to a boot code version. You want to have a system that maintains interoperability between as wide a range of boot and applications versions. The less interoperability there is, the bigger the configuration nightmare gets. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com I'm looking for work -- see my website!
On 6/7/2016 11:21 AM, Tim Wescott wrote:
> On Tue, 07 Jun 2016 06:43:04 -0700, Don Y wrote: > >> On 6/7/2016 3:49 AM, pozz wrote: >>> I will use one MCU with integrated USB OTG peripheral for two purposes: >>> >>> - bootloader for firmware upgrade from USB pendrive - USB connection to >>> an Android smartphone during application >>> >>> As you know, USB Host stack is a complex piece of code that has a high >>> Flash size. >>> In my scenario, I need two different USB Host: one for bootloader and >>> one for application. >>> >>> Is there a possibility to share the USB Host stack between bootloader >>> and application in some way? >>> >>> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. >> >> That depends on the capabilities that you require in each "instance" of >> the stack. Also, on the environment in which you expect each instance >> to operate! It's usually easier to write a piece of code to rely on >> MORE facilities (than less). >> >> Typically, boot loaders want to be as "slim" as possible. This helps >> ensure they are "correct" (no latent bugs that will cause your boot >> loader to misperform at a later date -- leaving you "stuck"). It also >> tends to make it easier to "step away" from the boot loader after the >> image has been pulled in -- less scaffolding to tear down as you >> transition to "application mode" (e.g., did you remember to disable any >> services upon which the loader relied that might conflict with services >> in the application's run-time?) > > If he needs to read USB drives from the bootloader, he's already crossed > the Rubicon as far as code complexity goes. Beyond that he just needs to > control risks.
I disagree. I can see lots of opportunities to trim a USB stack that is intended to: - have COMPLETE control of the hardware - only talk to one endpoint at a time ("ever") - has no need to poll - only support a single ("simple") device class - not support sub-devices - operate at a (reduced) data rate that *it* controls - only support bulk transfers (infinite retries) - etc. The OP can potentially pick a single "device" and refuse to "understand" other devices -- even those in the same device class! Look at the alternative of a full-fledged stack that has to potentially be able to talk to any device class, multiple endpoints per device, multiple devices concurrently, support isochronous transfers, etc. all WHILE ALSO SUPPORTING THE CONCURRENT PRESENCE OF COMPETING "APPLICATIONS". It's comparable to talking to a UART in *simplex* mode from userland without the benefit of a driver: just spinning on the status register waiting for a character to arrive, retrieving the character, then spinning again -- until the 289 characters that you EXPECT to receive have arrived (in that buffer[289]), THEN checking to see if they make sense before using them. Contrast that with pulling in characters while "doing something else", parsing the message on the fly and being able to tolerate variations in the data stream (without "Please reboot")
> I might implement a bootloader for the bootloader, for when things REALLY > mess up.
On Tue, 07 Jun 2016 12:02:47 -0700, Don Y wrote:

> On 6/7/2016 11:21 AM, Tim Wescott wrote: >> On Tue, 07 Jun 2016 06:43:04 -0700, Don Y wrote: >> >>> On 6/7/2016 3:49 AM, pozz wrote: >>>> I will use one MCU with integrated USB OTG peripheral for two >>>> purposes: >>>> >>>> - bootloader for firmware upgrade from USB pendrive - USB connection >>>> to an Android smartphone during application >>>> >>>> As you know, USB Host stack is a complex piece of code that has a >>>> high Flash size. >>>> In my scenario, I need two different USB Host: one for bootloader and >>>> one for application. >>>> >>>> Is there a possibility to share the USB Host stack between bootloader >>>> and application in some way? >>>> >>>> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. >>> >>> That depends on the capabilities that you require in each "instance" >>> of the stack. Also, on the environment in which you expect each >>> instance to operate! It's usually easier to write a piece of code to >>> rely on MORE facilities (than less). >>> >>> Typically, boot loaders want to be as "slim" as possible. This helps >>> ensure they are "correct" (no latent bugs that will cause your boot >>> loader to misperform at a later date -- leaving you "stuck"). It also >>> tends to make it easier to "step away" from the boot loader after the >>> image has been pulled in -- less scaffolding to tear down as you >>> transition to "application mode" (e.g., did you remember to disable >>> any services upon which the loader relied that might conflict with >>> services in the application's run-time?) >> >> If he needs to read USB drives from the bootloader, he's already >> crossed the Rubicon as far as code complexity goes. Beyond that he >> just needs to control risks. > > I disagree. I can see lots of opportunities to trim a USB stack that is > intended to: > - have COMPLETE control of the hardware - only talk to one endpoint at a > time ("ever") > - has no need to poll - only support a single ("simple") device class - > not support sub-devices - operate at a (reduced) data rate that *it* > controls - only support bulk transfers (infinite retries) > - etc. > > The OP can potentially pick a single "device" and refuse to "understand" > other devices -- even those in the same device class! > > Look at the alternative of a full-fledged stack that has to potentially > be able to talk to any device class, multiple endpoints per device, > multiple devices concurrently, support isochronous transfers, etc. all > WHILE ALSO SUPPORTING THE CONCURRENT PRESENCE OF COMPETING > "APPLICATIONS". > > It's comparable to talking to a UART in *simplex* mode from userland > without the benefit of a driver: just spinning on the status register > waiting for a character to arrive, retrieving the character, then > spinning again -- until the 289 characters that you EXPECT to receive > have arrived (in that buffer[289]), THEN checking to see if they make > sense before using them. > > Contrast that with pulling in characters while "doing something else", > parsing the message on the fly and being able to tolerate variations in > the data stream (without "Please reboot") > >> I might implement a bootloader for the bootloader, for when things >> REALLY mess up.
I suspect that unless you're an absolute freaking USB expert that you'd end up with fragile code. The first thing I would expect is code that only works with certain USB sticks. Not being a freaking USB expert I wouldn't know what else may happen -- but I'd be wary of Something Bad happening. But, yes, if you pulled it off it may well be smaller. -- Tim Wescott Wescott Design Services http://www.wescottdesign.com I'm looking for work -- see my website!
Il 07/06/2016 20:25, Tim Wescott ha scritto:
> On Tue, 07 Jun 2016 21:15:13 +1000, Clifford Heath wrote: > >> On 07/06/16 20:49, pozz wrote: >>> I will use one MCU with integrated USB OTG peripheral for two purposes: >>> >>> - bootloader for firmware upgrade from USB pendrive - USB connection to >>> an Android smartphone during application >>> >>> As you know, USB Host stack is a complex piece of code that has a high >>> Flash size. >>> In my scenario, I need two different USB Host: one for bootloader and >>> one for application. >>> >>> Is there a possibility to share the USB Host stack between bootloader >>> and application in some way? >>> >>> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. >> >> Overlay linkers used to do this kind of thing, but really the right >> answer now is to create a jump table or a C++ object that implements a >> virtual interface, and expose it from the bootloader. Then in the >> application code all you need is a single pointer. Essentially it >> becomes your USB Host BIOS. >> >> You just need to ensure that any and all library code that gets dragged >> in is appropriate to both environments, for example, any memory that >> gets allocated in the bootloader gets freed there too, not by a free() >> in the app code. >> >> Clifford Heath. > > What everyone has said so far, plus: > > I'm going to go ahead and call it a BIOS here, because that's basically > what you're doing. > > Whatever you do you need to make sure to make the API between BIOS and > application code as consistent as possible. So -- a jump table, or a > single address that gets called with parameters, or possibly a guaranteed- > unused interrupt that you hijack to branch to the BIOS. > > What you absolutely positively don't want to do is to just link the boot > code, then link the application code against the boot code's 'native' > addresses -- that will pretty much guarantee that each application > version will be firmly tied to a boot code version. You want to have a > system that maintains interoperability between as wide a range of boot > and applications versions. The less interoperability there is, the > bigger the configuration nightmare gets. >
Il 07/06/2016 20:25, Tim Wescott ha scritto: > On Tue, 07 Jun 2016 21:15:13 +1000, Clifford Heath wrote: > >> On 07/06/16 20:49, pozz wrote: >>> I will use one MCU with integrated USB OTG peripheral for two purposes: >>> >>> - bootloader for firmware upgrade from USB pendrive - USB connection to >>> an Android smartphone during application >>> >>> As you know, USB Host stack is a complex piece of code that has a high >>> Flash size. >>> In my scenario, I need two different USB Host: one for bootloader and >>> one for application. >>> >>> Is there a possibility to share the USB Host stack between bootloader >>> and application in some way? >>> >>> Most probably, I'll use a Cortex-Mx MCU with gcc toolchain. >> >> Overlay linkers used to do this kind of thing, but really the right >> answer now is to create a jump table or a C++ object that implements a >> virtual interface, and expose it from the bootloader. Then in the >> application code all you need is a single pointer. Essentially it >> becomes your USB Host BIOS. >> >> You just need to ensure that any and all library code that gets dragged >> in is appropriate to both environments, for example, any memory that >> gets allocated in the bootloader gets freed there too, not by a free() >> in the app code. >> >> Clifford Heath. > > What everyone has said so far, plus: > > I'm going to go ahead and call it a BIOS here, because that's basically > what you're doing. > > Whatever you do you need to make sure to make the API between BIOS and > application code as consistent as possible. So -- a jump table, or a > single address that gets called with parameters, or possibly a guaranteed- > unused interrupt that you hijack to branch to the BIOS. > > What you absolutely positively don't want to do is to just link the boot > code, then link the application code against the boot code's 'native' > addresses -- that will pretty much guarantee that each application > version will be firmly tied to a boot code version. You want to have a > system that maintains interoperability between as wide a range of boot > and applications versions. The less interoperability there is, the > bigger the configuration nightmare gets. > Thank for your suggestions and advices. I understand perfectly what you are saying, but it's very difficult for me to really implement them in C and linker script. It should be nice if there is some example, even about a totally different application, on the net that shows how to achieve what I'd like to do: sharing a set of functions (USB Host stack) between bootloader and application. Nowadays silicon manufacturers (NXP, Freescale, Microchip, Atmel, ...) publish a lot of example code for their evaluation boards, maybe one of those example shows what I'm trying to do.

The 2024 Embedded Online Conference