Share code between bootloader and application

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View
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.

Re: Share code between bootloader and application
On 07/06/16 20:49, pozz wrote:
Quoted text here. Click to load it

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.

Re: Share code between bootloader and application
On Tue, 07 Jun 2016 21:15:13 +1000, Clifford Heath wrote:

Quoted text here. Click to load it

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
We've slightly trimmed the long signature. Click to see the full one.
Re: Share code between bootloader and application
Il 07/06/2016 20:25, Tim Wescott ha scritto:
Quoted text here. Click to load it
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.


Re: Share code between bootloader and application
On Tue, 07 Jun 2016 22:57:38 +0200, pozz wrote:

Quoted text here. Click to load it

Then either your tools or you need upgrading.  Sorry if that's too blunt  
-- but there's no softer way to put it.

On the bright side, the self-upgrade should be fun.

Quoted text here. Click to load it

Locate a function or a jump vector at some fixed point in the boot code,  
in a way that it will never, ever change.  Then use an ioctl-like call to  
that one spot from the app code.  Make sure that the boot code has  
adequate RAM.

This WILL require dinking with the linker script, or with the project  
parameters if you use an IDE -- and if you use an IDE, you're almost  
guaranteed that the protection will be broken with some future upgrade.

Quoted text here. Click to load it

In general the example code that I see is written by applications  
engineers who are both fresh out of school and borderline incompetent.  
They serve to demonstrate how bits of hardware work, but they usually do  
so in the stupidest possible manner, which is usually also a manner that  
makes it impossible to incorporate them into reasonably-written code.

Not that I'm, like, biased or anything, but I would not expect the  
authors of the crap that I see to even be able to do what's necessary,  
much less express it in an understandable manner.

--  

Tim Wescott
Wescott Design Services
We've slightly trimmed the long signature. Click to see the full one.
Re: Share code between bootloader and application

Quoted text here. Click to load it

Yes.

--  
Grant Edwards               grant.b.edwards        Yow! MY income is ALL
                                  at               disposable!
We've slightly trimmed the long signature. Click to see the full one.
Re: Share code between bootloader and application
On Tuesday, June 7, 2016 at 6:49:16 AM UTC-4, pozz wrote:
Quoted text here. Click to load it

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

Re: Share code between bootloader and application
On 6/7/2016 3:49 AM, pozz wrote:
Quoted text here. Click to load it

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?)

Re: Share code between bootloader and application
On Tue, 07 Jun 2016 06:43:04 -0700, Don Y wrote:

Quoted text here. Click to load it

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
We've slightly trimmed the long signature. Click to see the full one.
Re: Share code between bootloader and application
On 6/7/2016 11:21 AM, Tim Wescott wrote:
Quoted text here. Click to load it

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")

Quoted text here. Click to load it



Re: Share code between bootloader and application
On Tue, 07 Jun 2016 12:02:47 -0700, Don Y wrote:

Quoted text here. Click to load it

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
We've slightly trimmed the long signature. Click to see the full one.
Re: Share code between bootloader and application
On 6/7/2016 1:23 PM, Tim Wescott wrote:
Quoted text here. Click to load it

My point isn't that you end up making it smaller.

Rather, that you write the *real* USB stack but with an eye towards
how you could implement it to run in different "environments".
(given the desire to have a single instance handle both applications)

Taking a "bootloader stack" and trying to use it as a "runtime
stack" is usually impractical as your hands have been tied by
the assumptions you made when writing it (see above).

Similarly, taking a "runtime stack" and trying to use it as
a "bootloader stack" leaves you just as disadvantaged.

You have to design a stack that *can* run in both environments
by carefully virtualizing the services on which it relies
(so the bootloader versions can essentially be stubbed as
virtual no-ops without a loss of functionality).

E.g., parameterize the implementation to that you can impose
constraints on it FROM THE OUTSIDE without having to recode
its inner workings.

My gesture recognizer will run in different "OS" containers
and with different capabilities -- without changing any of the
code but, instead, by stubbing the services on which it relies.
I.e., instead of issuing an SQL query sent over an encrypted
wireless network link to fetch templates from a real RDBMS, in
the "pared down" environment those queries return carefully
chosen ("design time") templates "out of ROM".  The code doesn't
need to know how complex the execution environment happens to be;
it just sees it through the same viewport.  No need for me to
provision RAM from which a "real" gesture recognizer's code
can execute (while the flash-based recognizer code just sits there
doing nothing)

Re: Share code between bootloader and application
pozz wrote:
Quoted text here. Click to load it

Tactically, this isn't that great of an idea. You sort of want the
bootloader to be ... firewalled from the application. Applications
updates fail. USB drives are unreliable.

If the applications update fails and leaves the device bricked....

Quoted text here. Click to load it



--  
Les Cargill


Re: Share code between bootloader and application
On 6/8/2016 4:31 AM, Les Cargill wrote:
Quoted text here. Click to load it

There's no reason that the stack can't be in a protected "boot sector"
of the flash -- and still accessed by the application (whether that
application is loaded into an "unprotected" portion of the flash
*or* executes out of RAM).


Re: Share code between bootloader and application
On Wednesday, June 8, 2016 at 7:28:47 AM UTC-4, Les Cargill wrote:
Quoted text here. Click to load it

If the USB code is within the bootloader, the application cannot
interfere with bootloading nor brick the device.

USB drivers ARE unreliable, weekly we have to tell a customer to
reformat a USB drive and try again (after FAT corruption on
pulling stick out prior writes completed).

Tactically it is an OK idea IFF you're willing to live with inability
to update the USB stack. Two weeks ago I had to update the USB stack
in a product, and that would not have been possible if the USB stack
was in the bootloader...

Hope that clarifies!
Best Regards, Dave

Re: Share code between bootloader and application

to:

Quoted text here. Click to load it

it's not the USB the problem here, it's how the data in the FAT FS are hand
led.
You would have the same problem with a SD Card.

Bye Jack

Re: Share code between bootloader and application
On Wednesday, June 8, 2016 at 10:20:42 AM UTC-4, Jack wrote:

itto:
Quoted text here. Click to load it
ndled.

Yep, but to the user its a "USB stick problem"
Too bad these buggers don't all use a journaling file system,
but then the file system code might not fit into small embedded devices...

Re: Share code between bootloader and application
On 6/8/2016 6:24 AM, Dave Nadler wrote:
Quoted text here. Click to load it

Nothing prevents the "application" from using a different instance of the
USB stack (though the OP doesn't ant to incur the resource penalty this
would require).

And, you can also arrange (at some potential peril) to allow the bootloader
to be updated in the field -- with the assistance of an application
(or portion thereof) designed to do exactly this.

[I use this approach to update the network stack in my bootloader.  But,
there are no "fallible humans" involved in the process!]


Re: Share code between bootloader and application
Dave Nadler wrote:
Quoted text here. Click to load it

1) Add an MicroSD card.
2) Use OTB.

IMO.

--  
Les Cargill

Site Timeline