Bootloader Slice and Dice

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

From what I read, the new winavr linker has issues with the bootloader where it starts creating bootloader.1..N section that will overlap with the data sections.

I know that one of the solutions is to combine the source files and I will try that. Some people mentioned that you can modify the linker script to handle this. Can someone let me know how?
Has there been any other resolutions to this?

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I made my bootoader as a normal program, but. In AVR Studio I've assigned the program to be programmed to the .text area which is reassigned to the desired memory section. You can see the fuse, bits and everything from Avrstudio.

No memory conversions or anything is needed. I'll try to remember post further instructions when I get back to home.

SW Design Engineer
Finland

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

keoma_,

The problem you describe will only occur if you don't write a "real" bootloader but, instead use BOOTLOADER_SECTION and use it in ore than one .c file in which case instead of a conglmerate .bootloader section the code will be enumerated into a .bootloader.1, .bootloader.2 and so on. None of this matters if you write the bootloader properly (and not a bolt on to a 0x0000 base app) and forget about BOOTLOADER_SECTION and instead simply use -Ttext=0x

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I'm using the BOOTLOADER_SECTION as you described. I'll have to do some research on how to do a "real" bootloader. That was the only way I've seen it done.

Thank you,

Sam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One thing I forgot to mention, I'm compiling the bootlaoder with my main application code. That's why I have been using the BOOTLOADER_SECTION attribute.
Can you help point me in the right direction as to how to compile application and bootloader code together and put the BL in the right section?

Thank you,

Sam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well IMHO the correct way to write a bootloader and an application are as two completely separate programs. Each has it's own reset vector, each has it's own interrupt vector table (unless you disable it), each has it's own C pre-amble and each has it's own main() entry point. The reason for doing this are that the AVR will need to be able to run with the bootloader alone and no app present (in case it's ever erased/replaced) so you don't want the bootloader tied to the app (except via a very controlled interface).

In this case you don't use BOOTLOADER_SECTION (which is just for bolting some SPM routines onto a main app) instad you build the main application completely normally as you would for any other app.

For the bootloader you do EXACTLY the same thing with just ONE change and that is a command you give to the linker to say -Ttext=0xnnnnn where nnnnn is the base address of the bootloader section in the code flash. This just takes a completely "normal" AVR application and moves everything (the reset vector, the vector table, the C preamble and everything in main() and beyond) up in memory so that the reset vector is based at byte address 0xnnnnn. You'd then also set the BOOTRST fuse in the AVR and, in future, when it boots it enters the reset vector at 0xnnnnn and executes the bootloader which ensures that there is a valid application in place at 0x0000 and then enters it.

IF they need to share routines then consider putting a table of function pointers (or similar) at the end of the BLS (that is the end of flash) or similar then both programs will know where to find the entry points to the routines. (other runtime linking methods are available - see loads of prior threads about this)

Cliff

EDIT: Oh and the perennial question that all this raises is that if I have app.hex and boot.hex how do I program BOTH into the AVR during factory programming? One answer would be just to program boot.hex into the AVR with ISP/JTAG and then deliver the app.hex by the actual bootloader download mechanism but perhaps the easier is to take the two .hex files and "glue" them together using SREC to make a combined.hex and then use that for factory programming.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff,

Thank you,

Sam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Cliff,

thanks for such valuable info. I have one question though, where can I find the SREC function? I don't see it in AVR Studio. I found one in forgesource.net
http://srecord.sourceforge.net/

is this the one that you mentioned?

Thanks!!

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Leo,

As you posted in GCC forum and as you mentioned AVR Studio I have a pretty strong suspicion that you have installed your avr-gcc as a result of WinAVR. If that's the case take a look at:

/winavr/bin/srec*.exe

It's actually a group of utilities. I guess srec_cat.exe is the one you'll use. It's documented in:

/winavr/doc/srecord/srecord-*.pdf

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Cliff,

Thanks for your prompt reply. I found the file under winavr directory. yes, it is srec_cat written by Peter Miller I believe. I also found a forum where it discusses about command line problems when invoking srec_cat.

http://www.avrfreaks.net/index.p...

Again, thanks, I will take a look at the pdf file.

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi again Cliff,

I found a thread on the net, and it says that you "has done an outstanding job of describing the various forms of bootloader,and why one might choose one form over another. " do you know where can I find that thread??

Thanks!

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I tend to "glue" the botloader and the app together using a simple text editor(notepad, for example). It's fairly simple if you have a basic understanding of .HEX files.

Quebracho seems to be the hardest wood.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used srec_cat to glue my boot.hex and main.hex; and also set the bootrst fuse; and somehow, the microcontroller always go to the main.hex upon reset. i did compile my boot.hex with link option -Ttext=0x3800; which is the start address of the BL section.

I also glue the boot.hex and main.hex with notepad; there are 2 lines of hex dump that I don't quite understand, and it is usually place at the end of the .hex file

:0439D000F894FFCF99
:0400000300003800C1

i do know that :00000001FF stands for end of file, so I only place one at the end of the bootloader code.

Here is what I have


:0A1EA000CDBFED010895F894FFCFC7
:101EAA00414E30303030613030306861796173686A
:041EBA00693061002A

:0439D000F894FFCF99
:0400000300003800C1

:00000001FF

the bootloader simply blinks a LED, and never jump to application code; I did this to test if the microcontroller is really booting from the BL section.

Am I missing something? Thanks for helping,

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Well IMHO the correct way to write a bootloader and an application are as two completely separate programs. Each has it's own reset vector, each has it's own interrupt vector table (unless you disable it), each has it's own C pre-amble and each has it's own main() entry point. The reason for doing this are that the AVR will need to be able to run with the bootloader alone and no app present (in case it's ever erased/replaced) so you don't want the bootloader tied to the app (except via a very controlled interface).


That is worse because now you lose the ability to store stuff like printf in the bootloader section and call from the app.
Quote:

In this case you don't use BOOTLOADER_SECTION (which is just for bolting some SPM routines onto a main app) instad you build the main application completely normally as you would for any other app.

Or instead use BOOTLOADER_SECTION for all the stuff to share code between app and bootloader. Bootloader has it's own ISRs but they have to be declared as such.
Quote:

For the bootloader you do EXACTLY the same thing with just ONE change and that is a command you give to the linker to say -Ttext=0xnnnnn where nnnnn is the base address of the bootloader section in the code flash. This just takes a completely "normal" AVR application and moves everything (the reset vector, the vector table, the C preamble and everything in main() and beyond) up in memory so that the reset vector is based at byte address 0xnnnnn. You'd then also set the BOOTRST fuse in the AVR and, in future, when it boots it enters the reset vector at 0xnnnnn and executes the bootloader which ensures that there is a valid application in place at 0x0000 and then enters it.
[\quote]
It's nice that they work the same way,
IF they need to share routines then consider putting a table of function pointers (or similar) at the end of the BLS (that is the end of flash) or similar then both programs will know where to find the entry points to the routines. (other runtime linking methods are available - see loads of prior threads about this)

And hardcode their offsets? What if you add a new function in the bootloader section next week? I can write a bootloaderloader anyday which updates the bootloader, so both codes can remain dynamic and changing, and the end result is you would be able to update app and bootloader and not notice the problem.

Disadvantage is before you distribute binaries make sure you test it so it doesn't cause "bricking"

Sean

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

That is worse because now you lose the ability to store stuff like printf in the bootloader section and call from the app.

What on earth would printf() be doing in a bootloader? But anyway, OF COURSE you can share BL routines to the app. The one thing you cannot do is share app routines to the BL as the app may not always be there (consider what happens if the power is pulled half way through an app reprogramming)

And hardcode their offsets? 

No the ONLY hard coded thing is a 16 bit value that is the address of where a table of function pointers is located. It doesn't have to be hardcoded anyway - say the BL jumps into the app with a "JMP 0x0000" then you could, for example, put the pointer in R24/R25. If you manage to update the BL and want to expose new functions you add them to the END of the struct of f_ptr's who's base is being passed.

Quote:
I can write a bootloaderloader anyday which updates the bootloader,

It's been suggested a few time but I don't know of anyone who'd ever succeded in updating the bootloader in an AVR with an SBL - have you REALLY done this? Bootloader are usually "fire and forget" - it's the one bit of the software you have to get right on day one as it's the one bit of the software that you can never change. That's why it's probably best to put the absolute minimum (comms and SPM routines) into it.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

need help on setting up bootrst.

I compile a simple main() application starting at address 0x0000. I have bootrst option cleared in AVR studio 14. the application runs as expected.

I changed bootsize to 2K words; and program bootrst fuse in AVR studio, have same main() program at address 0x0000 and the microcontroller supposse to boot at address 0x3800, but it still booting from address 0x0000.

Am I missing something??

Thanks for your help,

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I changed bootsize to 2K words; and program bootrst fuse in AVR studio, have same main() program at address 0x0000 and the microcontroller supposse to boot at address 0x3800, but it still booting from address 0x0000.

Nope, I'll bet it IS booting at 0x3800 where it just finds a sea of 0xFF's that it executes as "NOPs" (they are actually undefined but it's been observed that 0xFFFF acts as a NOP). It then wraps beyond the end of code flash and goes back to 0x0000 where it appears to run your program.

Try putting something DIFFERENT at 0x3800 and see which of the two executes.

(by the way to move a program to 0x3800 use -Ttext=0x3800 in the LDFLAGS)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks so much. OK, this is what I did.

i did a small program that just flashes a LED on the STK500. it takes only 346Kbytes of flash. main() program flashes LED0, and boot() flashes LED1.

after compiling the main() program, I went and open in wordpad the main.hex file, and the start address is 0x0000 as expected. the end of file markup is <:00000001FF>

on the boot() program, I set under [Linker Options] -Ttext=0x3800; and also in the memory settings added a section called ".text = 0x3800" of flash. using the default makefile from winavr.

when it compiles it says

avr-gcc -mmcu=atmega32 -Ttext=0x3800 -Wl,-Map=mega32L_boot4.map -Wl,-section-start=.text=0x7000 mega32L_boot4.o -o mega32L_boot4.elf

I check the boot.hex and it starts at address 0x3800 as expected and the file end with markup <:00000001FF>.

I did 2 tests:

1. Program boot() after main() without erasing the flash. and have the reset vector at BL. Result: it always execute main() upon reset.

2. Glue main.hex and boot.hex in wordpad, by removing only the end of file markup at the end of main.hex and paste it at the beggining of boot.hex file. program the flash with merged.hex by erasing the flash before programming. Result: main() is always executed upon reset.

So far, it is still behaving exactly the same; executing from main() regardless of bootrst

any thoughs??

Thanks so much for helping,

Leo;

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I did another test. I combine the main() and boot() in the same code in C this time by using BOOTLOADER_SECTION of boot.h.

I setup a memory section called .bootloader in memory settings under configuration. and it works. with bootrst = 0 it boot from the BL section; bootrst = 1 it boot from main().