[FAQ] [C] (writing a) Bootloader FAQ

Go To Last Post
83 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Planning to create a custom bootloader? This document answers many of the questions you may have. Most of the concepts covered within are not discussed thoroughly in datasheets, and various tips for designing a robust bootloader are provided.

Table of Contents

1. How do I get started?
2. What are the NRWW and RWW regions?
3. How does the bootloader update the application?
4. Can a bootloader update fuses?
5. What is BOOTLOADER_SECTION in for?
6. How do I program the bootloader to the MCU?
7. How do I program both the application and the bootloader?
8. Can a bootloader use interrupts?
9. Should the bootloader or the application run first?
10. How does the bootloader know when to start the application?
11. How does the bootloader start the application?
12. How can the bootloader be sure the application is intact?
13. Can the bootloader use code built into the application?
14. Can the application use code built into the bootloader?
15. Why can't global variables be accessed from shared functions?
16. Can the application use an ISR built into the bootloader?
17. How can a shared ISR access global data?
18. Can I save space in a bootloader with few or no ISRs?

Thanks to Cliff Lawson for reviewing and contributing to this FAQ.

Edit May 19, 2009: Fixed a few typos in the FAQ (old download count 30)

Attachment(s): 

-Brad

Last Edited: Tue. May 19, 2009 - 05:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is great

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

Nice.
I think you should add something about what AVR models support bootloaders. Are there any general rules about this, like only ATmegas or all AVRs - only devices above xx kB flash and/or xx number of pins - or other general rules to easily tell what devices support bootloaders without going through all datasheets whenever you want to find one that supports bootloaders.

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

A quick scan through the datasheets I happen to have on my drive here suggests that the only chip I can find that does not have a "self programming the flash" section is the tiny12. Even the 1K tiny13 has that section. Though I guess the true indicator of "real" bootloader support is the presence of a BOOTRST fuse.

Not sure if anyone has ever waded through the entire datasheet collection to see which DO and which DON'T have BOOTRST though?

EDIT: Ah ha! Just thought of a way to identify them:

C:\WinAVR-20090313\avr\include\avr>grep FUSE_BOOTRST *.h
io90pwm1.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
io90pwm216.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
io90pwm2b.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)  /* Select Reset Vector */
io90pwm316.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
io90pwm3b.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)  /* Select Reset Vector */
io90pwm81.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector  */
io90pwmx.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
io90scr100.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
ioa6289.h:#define FUSE_BOOTRST ~_BV(0)  /* Select reset vector */
iocan128.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iocan32.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iocan64.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom128.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom1280.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom1281.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom1284p.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)  /* Select Reset Vector */
iom128rfa1.h:#define FUSE_BOOTRST    ~_BV(0) /* Select Reset Vector */
iom16.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom161.h:#define FUSE_BOOTRST     (unsigned char)~_BV(6)
iom162.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom163.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom164.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom165.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom165p.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom168.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)
iom168p.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)
iom169.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom169p.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom16m1.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom16u4.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom2560.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom2561.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom32.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom323.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom324.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom325.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom3250.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom328p.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)
iom329.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom3290.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom32c1.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom32hvb.h:#define FUSE_BOOTRST   (unsigned char)~_BV(0)  /* Select Reset Vector */
iom32m1.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom32u4.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)  /* Select Reset Vector */

iom32u6.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom406.h:#define FUSE_BOOTRST (unsigned char)~_BV(3)
iom64.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom640.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom644.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom645.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom6450.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom649.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom6490.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom64c1.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom64m1.h:#define FUSE_BOOTRST  (unsigned char)~_BV(0)  /* Select Reset Vector */
iom8.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom8515.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom8535.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iom88.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)
iom88p.h:#define FUSE_BOOTRST (unsigned char)~_BV(0)
iousb1286.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iousb1287.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iousb162.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iousb646.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iousb647.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iousb82.h:#define FUSE_BOOTRST     (unsigned char)~_BV(0)
iox128a1.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox128a3.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox16a4.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox16d4.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox256a3.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox256a3b.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox32a4.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox32d4.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox64a1.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */
iox64a3.h:#define FUSE_BOOTRST  ~_BV(6)  /* Boot Loader Section Reset Vector */

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

clawson wrote:
A quick scan through the datasheets I happen to have on my drive here suggests that the only chip I can find that does not have a "self programming the flash" section is the tiny12. Even the 1K tiny13 has that section. Though I guess the true indicator of "real" bootloader support is the presence of a BOOTRST fuse.

Thank you for the list.

I don't think I have ever seen a bootloader that supports AVRs without "Read-While-Write Self-Programming" (AVRs with BOOTRST fuse).
Is is actually possible to make a bootloader for devices without BOOTRST? And if so, why don't we see any bootloaders supporting these devices? OR does anyone have a link to a bootloader supporting an AVR without BOOTRST fuse?

For example ATmeaga48PA and 88PA share the same datasheet: http://www.atmel.com/dyn/resourc...
But only the 88PA has the Read-While-Write Self-Programming (BOOTRST fuse). (See section 26. Boot Loader Support – Read-While-Write Self-Programming, ATmega88PA)
I have seen many bootloaders supporting 88PA, but haven't seen any also supporting 48PA without the BOOTRST fuse.

I think ATmega88PA is the smallest and cheapest AVR that supports bootloaders. There's no ATtiny's, regular "old" AT90Sxxx (or ATmeaga48PA as I mentioned) in your list of devices with BOOTRST fuse. And I have never seen a bootlaoder for these devices either.
Looks like all ATmegas with >= 8kB flash (all of them except ATmega48(PA) has the BOOTRST fuse.

Last Edited: Tue. May 19, 2009 - 04:04 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is is possible to make a bootloader for devices without BOOTRST? And if so, why don't we see any bootloaders supporting these devices?

That's really almost the same question about reprogramming a bootloader with a bootloader. The problem is doing SPM in the same section as is being replaced. In theory it can be done by having two lots of SPM code. (often refrerred to as a Primary Boot Loader and a Secondary Boot Loader PBL/SBL). First the PBL would receive and then program the SBL in another part of the same section,then control would pass to the SBL which would receive and program a replacement for the PBL. But this kind of opens the system up to "rug from under your own feet" problems. Clearly the intention of Atmel in providing and allowing SPM to run in the single section AVRs was that the flash *could* be self programmed but I imagine the intention was simply so a datatable or something could be replaced - not that the code could pull the rug from under its own feet.

So whether anyone has ever achieved a complete self-reprogram in either the entire flash of a single section AVR or within the NRWW section of a dual section AVR is one of the great unsolved mysteries.

Some folks suggest that things like hard coding boot routine addresses in the app is a "dangerous thing" in case the bootloader itself is ever replaced but until someone actually manages to replace an AVR's own bootloader I think it's a moot point.

Cliff

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

clawson wrote:
Some folks suggest that things like hard coding boot routine addresses in the app is a "dangerous thing" in case the bootloader itself is ever replaced but until someone actually manages to replace an AVR's own bootloader I think it's a moot point.

I think there are two risks with hard-coding addresses like this.

1. During design and development, there may be a bunch of prototype devices floating around and more than one person working on a project. It is just too easy to update the bootloader with an ISP and forget to update hard-coded addresses and rebuilt the application. Or even remember to update addresses, but miss one function by mistake. Its both a hassle to work like this and a potential time waster if someone screws up.

2. Even worse is if after releasing devices into the wild you find a bug in the bootloader that should be fixed. If you fix this bug for new devices without recalling or discarding all existing devices, you now have a potentially tricky application update problem. You need two versions... one for the old BL and one for the new BL.

I totally agree that a bootloader should be rock-solid and hopefully never change once a device has shipped. But if I've learned anything after decades of software work it is that anything can be screwed up ;)

I am thinking of a senario like this: A consumer device has shipped 5,000 units already when you start getting reports that app firmware updates don't work on 3+ year old iMacs. You find that there is a small USB tweak to the bootloader that could fix the issue. Given that most device owners are unaffected by the problem, you update the BL for new devices and simply replace old ones when people report a problem. But if you've hard-coded addresses you now have up to 5,000 devices that need a different version of the app firmware.

Sure, your bootloader and application could have version numbers to report an error if they are incompatible, but a jump table (question #14) is an easy and small solution that will give your customers a better experience. I personally think it is hard to justify taking even a small risk on hard-coded addresses when an easy improvement is available.

-Brad

Last Edited: Tue. May 19, 2009 - 06:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

AndersAnd wrote:
I think you should add something about what AVR models support bootloaders. Are there any general rules about this, like only ATmegas or all AVRs - only devices above xx kB flash and/or xx number of pins...

Looks like Cliff uploaded a good snapshot of the current support. I don't really want to add this to the FAQ since it will constantly be changing. Also I think it is safe to assume that except for a few speciality AVRs, most new chips are going to support bootloaders with RWW/NRWW sections.

-Brad

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

schickb wrote:
Also I think it is safe to assume that except for a few speciality AVRs, most new chips are going to support bootloaders with RWW/NRWW sections.

Sorry, but I think it's safe to say that this is not true at all.
Best eaxmple is the ATmega48PA which is one of the newset of all the AVRs, and even though it's almost identical bigger brother ATmega88PA has a bootloader section, this is not the case with 48PA.
As I mentioned ATmega48PA + all of the ATtinys doesn't have a bootloader section.
Another good example is ATtiny88 which is one of the newset ATtinys (kind of a discount version of ATmega88PA) and this does not have a bootloader section even though it has 8kB of Flash like ATmega88PA with bootlaoder does: http://www.atmel.com/dyn/resourc...
Maybe it's safe to say all new ATmegas with flash >= 8kB has a bootloader section, but that none of the AT90Sxxxx or ATtinys (brand new or old) has a bootlaoder section, even the largest one with 8kB flash.

My point with thsi whole discussion was that one can get the impression that all AVRs has a seperate boot section, which is not true.
I can understand why you don't want a complete list of AVRs with seperate boot section. But I think it's a good idea to mention that only the largest AVRs has a seperate boot section.
It could be more specific and say currently none of the AT90Sxxxx or ATtiny has boot sections and only ATmegas with >= 8kBflash.
Just make the reader aware that the smallest AVRs doesn't have a boot section.

It makes sense why they don't add bootloader sections to the smallest flash size AVRs, as a bootlaoder in itself takes up quite a lot of flash.
But ATtiny88 could have had a bootloader when ATmega88PA does. But they have probably left it out in all ATtinys even the biggest ones to reduce cost.

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

AndersAnd wrote:
schickb wrote:
Also I think it is safe to assume that except for a few speciality AVRs, most new chips are going to support bootloaders with RWW/NRWW sections.

Sorry, but I think it's safe to say that this is not true at all.
Best eaxmple is the ATmega48PA which is one of the newset of all the AVRs, and even though it's almost identical bigger brother ATmega88PA has a bootloader section, this is not the case with 48PA.
As I mentioned ATmega48PA + all of the ATtinys doesn't have a bootloader section.

Well by "speciality" (or is that specialty) I mostly meant low flash devices. Beyond the Tinys, I only count 9 current AVRs with < 8K of flash and 7 of those are automotive.

But your point it taken, you can't assume all devices have a proper bootloader section without checking.

I'd just rather have Atmel maintain such a list in their parametric product table than do it myself ;)

-Brad

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

I posted the list above - I think you can take the .h files in GCC to be as definitive as either the XML partdescription files or the datasheets

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

schickb wrote:
Well by "speciality" (or is that specialty) I mostly meant low flash devices. Beyond the Tinys, I only count 9 current AVRs with < 8K of flash and 7 of those are automotive.

Atmel's definition of speciality AVRs is all the ones not listed under the generic ATtiny and ATmega sections (and maybe XMEGA) here: http://www.atmel.com/dyn/product...

So speciality AVRs would be Automotive AVR, Lighting AVR, AVR Z-Link, Battery Management AVR, CAN AVR, USB AVR and LCD AVR.

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

clawson wrote:
I posted the list above - I think you can take the .h files in GCC to be as definitive as either the XML partdescription files or the datasheets

I just don't want to update the FAQ every time Atmel adds a new part. Maybe the best solution would be to add another entry to the document that tells people how to grep the avr-libc headers to figure it out for themselves.

And at the same time maybe someone should email Atmel and ask them to add that to their parametric tables ;)

-Brad

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

Quote:

Maybe the best solution would be to add another entry to the document that tells people how to grep the avr-libc headers to figure it out for themselves.

Or I'll just do that grep and post it here each time a new WinAVR is released. ;-)

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

schickb wrote:
Planning to create a custom bootloader? This document answers many of the questions you may have. Most of the concepts covered within are not discussed thoroughly in datasheets, and various tips for designing a robust bootloader are provided.

Hi, Thanks for the document, sounds like just what I need. But I thought I'd let you know it's entirely unreadable with the built-in Mac OS X "Preview" Program.
(See the Screenshot).
What PDF writer did you use?

Attachment(s): 

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

thefool wrote:
Hi, Thanks for the document, sounds like just what I need. But I thought I'd let you know it's entirely unreadable with the built-in Mac OS X "Preview" Program.
(See the Screenshot).
What PDF writer did you use?

Stange. I have OS X 10.5.7 and it looks perfect in Preview (which is the default Mac pdf viewer). My version of preview says "Version 4.2 (469.5)".

Does this work or not work for anyone else on a Mac?

I used Open Office 3.0 to save it as a PDF. I wonder if your download was corrupted. I've seen that before particularly when the machine has a virus (which might be appending itself to downloads).

-Brad

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

I've had the exact same problem with another PDF from openoffice, maybe it doesn't stick to the standard...
I'm using Mac OS X 10.5.6 and Preview 4.1 (469.4)
I'll update my system and see if the error is resolved.

You've actually seen a virus infected Mac? What virus was that? (Or are you talking about a PC with similar symptoms?)

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

OK, updated to 10.5.7 (and Preview 4.2) and it's perfectly readable now. I guess there was an error in Preview 4.1...

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

thefool wrote:
You've actually seen a virus infected Mac? What virus was that? (Or are you talking about a PC with similar symptoms?)
PC with similar symptoms, but there are Mac viruses.

Anyway, glad updating your system helped. Hope you find the FAQ useful.

-Brad

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

schickb wrote:
there are Mac viruses.

I know, I've just never actually witnessed one :-)

schickb wrote:
Hope you find the FAQ useful.

Very much so, thanks a lot for that!
I'm just writing a bootloader and was wondering about the things you adressed in 10. and 11. So you've helped me understand quite a bit more!

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

AndersAnd wrote:
I don't think I have ever seen a bootloader that supports AVRs without "Read-While-Write Self-Programming" (AVRs with BOOTRST fuse).
Is is actually possible to make a bootloader for devices without BOOTRST? And if so, why don't we see any bootloaders supporting these devices? OR does anyone have a link to a bootloader supporting an AVR without BOOTRST fuse?

Why you not look on the projects page?

Bootloader for ATtiny13 ... ATmega2561:

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

Peter

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

Hi,

I'm not able to download the pdf file. The browser is pointing to index.php,

Leo;

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

hayashi_leo wrote:

I'm not able to download the pdf file. The browser is pointing to index.php

It still works find for me. I assume you are clicking the "Download" link in the very first post on page 1 of this topic. You can also try right clicking that link and selecting "save link as".

-Brad

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

The board used to have this problem but if the downloaded file gets called index.php just rename it to boot.pdf and it should still work

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

Thanks! it works!!

Leo;

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

danni wrote:
AndersAnd wrote:
I don't think I have ever seen a bootloader that supports AVRs without "Read-While-Write Self-Programming" (AVRs with BOOTRST fuse).
Is is actually possible to make a bootloader for devices without BOOTRST? And if so, why don't we see any bootloaders supporting these devices? OR does anyone have a link to a bootloader supporting an AVR without BOOTRST fuse?

Why you not look on the projects page?
Bootloader for ATtiny13 ... ATmega2561:
http://www.avrfreaks.net/index.p...

Thank's for the heads up Peter, I missed that.
Does this bootloader use a software UART for all devices?
ATtiny13 and ATtiny45 doesn't have hardware UART, ATtiny2313 is the only ATtiny with UART.

AVR-----------user size--programming time
-----------------------------------------
ATtiny13-------606 Byte---0.77 seconds
ATtiny2313----1630 Byte---2.86 seconds
ATtiny45------3646 Byte---3.52 seconds
ATmega8-------7680 Byte---1.81 seconds
ATmega16-----15872 Byte---3.35 seconds
ATmega32-----32256 Byte---5.33 seconds
ATmega644----64512 Byte---8.19 seconds
ATmega2561--261120 Byte--32.75 seconds

At what BAUD-rate is this measured?

I guess "user size" is the same as the maximum program space flash left with the bootlaoder installed?
So this bootlaoader takes up this much flash in the different devices:

AVR-----------user size--------bootlaoder size------
----------------------------------------------------
ATtiny13-------606 Byte----1*1024-606    =  418 Byte
ATtiny2313----1630 Byte----2*1024-1630   =  418 Byte
ATtiny45------3646 Byte----2*1024-1630   =  450 Byte
ATmega8-------7680 Byte----8*1024-7680   =  512 Byte
ATmega16-----15872 Byte---16*1024-15872  =  512 Byte
ATmega32-----32256 Byte---32*1024-32256  =  512 Byte
ATmega644----64512 Byte---64*1024-64512  = 1024 Byte
ATmega2561--261120 Byte--256*1024-261120 = 1024 Byte 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
typedef void (*PF_VOID)(void);
typedef void (*PF_WHATEVER)(uint8_t);

...

static __inline__ void call_func3(uint8_t arg)
{ ((PF_WHATEVER) (0x3FE2/2))(arg); }

What are functions like this called, and how do I create them for functions that need multiple parameters? Thanks, and great tutorial.

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

jgiers wrote:
Quote:
typedef void (*PF_VOID)(void);
typedef void (*PF_WHATEVER)(uint8_t);

...

static __inline__ void call_func3(uint8_t arg)
{ ((PF_WHATEVER) (0x3FE2/2))(arg); }

What are functions like this called, and how do I create them for functions that need multiple parameters? Thanks, and great tutorial.


Those are call function pointers. Here is an entire tutorial about function pointers in C/C++ http://www.newty.de/fpt/index.html

To add more parameters, just add them to the declaration and the call. The declaration would look something like

typedef void (*PF_WHATEVER2)(uint8_t, uint8_t);

-Brad

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

Hi;

question for FAQ #8, Can a bootloader use interrupts?

I would like to use interrupt with USART on my bootloader rather than polling.

So before the bootloader main(); I set
MCUCR = (1<<IVCE);
MCUCR = (1<<1VSEL);

this allocates the interrupt table into the BLS.

my question is how to restore the interrupt table to the application section?

is this the right method? place this code before jumping to application section;

MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL);

??

Thanks!!

Leo;

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

hayashi_leo wrote:

my question is how to restore the interrupt table to the application section?

is this the right method? place this code before jumping to application section;

MCUCR = (1<<IVCE);
MCUCR = (0<<IVSEL);


That should work, although shifting zero isn't going to do anything. The code below is the same as yours. See faq #11 for an example of this:

MCUCR = (1<<IVCE);
MCUCR = 0;

If you want to be sure to clear only the IVSEL bit you'll need:

MCUCR = (1<<IVCE);
MCUCR &= ~(1<<IVSEL);

But you'll need to make sure the second write finished within 4 instructions of the first write (look at the ASM to know). The compiler should reduce "~(1<<IVSEL)" to a constant, and you'll be fine. But check to be sure.

-Brad

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

Thanks!!!

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

I didn't find Download in this post.
Thanks!

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

HGunther wrote:
I didn't find Download in this post.
Thanks!

There are so many posts in the thread so that it is divided into two pages. At the top and bottom of the pages there are page selectors. Click the "1" and in the ultimately first post there is an attachement.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Also note that I don't think your see attachments if you are not logged in. But the first post definitely has a PDF in it.

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

clawson wrote:

So whether anyone has ever achieved a complete self-reprogram in either the entire flash of a single section AVR or within the NRWW section of a dual section AVR is one of the great unsolved mysteries.

Some folks suggest that things like hard coding boot routine addresses in the app is a "dangerous thing" in case the bootloader itself is ever replaced but until someone actually manages to replace an AVR's own bootloader I think it's a moot point.

Cliff

Well we did... We had a bogus bootloader in a mega32?. (something with interrupts still enabled during programming). So sometimes it would not update correctly and the system would hang, luckily we could reboot it remote and re-upload the software.
So this is (roughly) what we did:
We figured out where our SPM function was.
Created special software containing a new bootloader as payload.
Used the existing bootloader to upload it.
Using the existing SPM function to flash a new SPM function to the end of the bootloader section.
Use the new SPM function to update the entire bootloader.
Reboot and let the bootloader load the normal software.
Yes it involved hard coded addresses, some special tricks to harden the flow against powerdowns etc. There was only one moment where we could not recover if we should have had a power failure.
It was some pretty nasty coding, but we now have a defined SPM function at the very end of our bootloader. And the bootloader has at least one bug less ;)

We also did bootloaders for Atmega48. (we did multiple actually) The code to do it is dead ugly and I was looking for pretty ways of doing it when came across this topic. Just wanted to let you know.

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

I'm attempting to write my first bootloader and this the best explaination I've seen so far on the subject. However I have a question about setting up the environment to compile one. I use AVR Studio with a WinAVR installation, and have never had to muck around with the make files. Is there a way to specify to AVR Studio what changes need to be made to the make file to insure the code gets placed at the proper base address?

I also have another question that is outside of the scope of your fantastic document, but maybe somebody can point me in the right direction. I have a VB.NET app that communicates with my ATMEGA168, and I would like to be able to have it update the controller code if necessary. I don't expect anybody to give code examples, but if you know of any examples out in the wild, please let me know.

And thanks again for the great write up!

Wayne

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

Quote:

Is there a way to specify to AVR Studio what changes need to be made to the make file to insure the code gets placed at the proper base address?

Project menu
Configuration Options
Memory Settings
[Add]
Type = Flash (already selected)
Name = .text
Address = 0x1C00 (for example)
[OK]
[OK]

In this example (for mega16) I specified the address as 0x1C00 which is the WORD address for the BLS boundary address. When the code is built this can be seen as:

avr-gcc -mmcu=atmega16 -Wl,-Map=test.map -Wl,-section-start=.text=0x3800 empty.o test.o    -lm  -o test.elf

during the link. Notice how Studio has passed the 0x1C00 (word) address that was entered as 0x3800 (byte = 2* word) address because while Studio uses word addresses for flash GCC needs byte addresses.

The result of this is:

Disassembly of section .text:

00003800 <__vectors>:
    3800:	0c 94 2a 1c 	jmp	0x3854	; 0x3854 <__ctors_end>
    3804:	0c 94 47 1c 	jmp	0x388e	; 0x388e <__bad_interrupt>
    3808:	0c 94 47 1c 	jmp	0x388e	; 0x388e <__bad_interrupt>
    380c:	0c 94 47 1c 	jmp	0x388e	; 0x388e <__bad_interrupt>
    3810:	0c 94 47 1c 	jmp	0x388e	; 0x388e <__bad_interrupt>
etc.

which confirms that everything including the reset jump and the ISR vector table have been moved to byte address 0x3800

As for the VB thing I guess what you are asking is "how do I do COM ports from a VB program?" See examples written by Joe Pardue (smileymicros). I think he used to use VB and now uses C# but the M$ APIs you use are virtually identical (as is the case with all the .Net languages)

Cliff

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

TracerH wrote:
I'm attempting to write my first bootloader and this the best explaination I've seen so far on the subject. However I have a question about setting up the environment to compile one. I use AVR Studio with a WinAVR installation, and have never had to muck around with the make files. Is there a way to specify to AVR Studio what changes need to be made to the make file to insure the code gets placed at the proper base address?
I've done this using the Project Options without a special makefile (AVRStudio now generates it for you) but I don't remember all the details at the moment other than that I always had to double check that the bootloader address was correct. It seemed to want to randomly reset or not remember it properly between uses. IIRC the problem was in the Memory Settings of the Project Options.

TracerH wrote:
I also have another question that is outside of the scope of your fantastic document, but maybe somebody can point me in the right direction. I have a VB.NET app that communicates with my ATMEGA168, and I would like to be able to have it update the controller code if necessary. I don't expect anybody to give code examples, but if you know of any examples out in the wild, please let me know.
Are you looking for some sort of GUI that creates the parameter list for avrdude and then calls it to upload a hex file to your bootloader? If so, I am just now tying up loose ends on a C# .NEt project that does this. I plan to post the code here in a week so be on the lookout for AVRUP-V1. Look that over and if you really need me to, I can do an auto port from C# to VB. Let's not hyjack this thread so if you are interested either start a new thread 'avrdude GUI in .NET?' or wait till I post my code.

[edit]AND along comes Cliff while I'm fumbling around.[/edit]

Smiley

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

Wow, you guys are fast and informative! Many thanks for the information. Since reviewing the docs here, I have found the AVR109/AVR911 app notes. I will look at the setup in AVR Studio when I try this.

As for the VB.NET end, I will review the existing code and eagerly await the new version. (C# and VB are basically the same.) I am hoping to recreate the download code without using AVRDUDE. I am quite experienced in using the RS-232 port from .NET code, so more looking for information on parsing the hex file format for download. Maybe I can find what I need in the source to AVROSP.

So, again, my humble thanks to you guys for the speedy help. And sorry for the thread hijacking!

Wayne

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

Hello,

Thanks for this tutorial! But I still have a problem concerning question #1. Not gone far yet...

I want to write a bootloader for Mega168. I set the BOOTRST and BOOTSZ to 1024 words. I use AVR Studio with WinAVR, gcc and JTAG ICE MKII.

I need to write the bootloader in the bootloader section so I did as in the FAQ. In the custom options, I added "-Wl,--section-start=.text=0x3800". When I load the code, it is still at 0x00. I look in the view memory to see where it is. I load it with the JTAG MKII using Debug Wire (start debugging).

Questions:

1- Is it ok to load a bootloader with JTAG MKII and DW?

2- If not, wich tool to use?

3- In my bootloader program, I make a normal AVR project with a "int main (void) {}" function. Is this ok?

4- Am I missing something to put the code at 0x3800 (0x1C00 word adress)?

Thanks a lot!

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

OK, I found it. I should use more often this forum so I could find more answers myself... I read this post (did not get my attention the first time) pointing on the memory settings.

Project menu
Configuration Options
Memory Settings
[Add]
Type = Flash (already selected)
Name = .text
Address = 0x1C00 (for example)
[OK]
[OK]

Thanks to Cliff.

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

1) No problem whatsoever

2) not that you have to but I'll just point out that JTAGICEmkII is also an ISP programmer and can be used very like an AVRISPmkII

3) that's EXACTLY what you should do - the BL should be a completely standalone program with its own reset vector, C pre-amble and main() function - so you build it just like any other program with the single change to the .text base address

4) Your --section-start *SHOULD* have worked (you may be interested to know that -Ttext=.... is shorthand for the same) however Studio can make this easier for you. Go to Config Options on the Project menu and select the fourth icon down on the left ("Memory settings"). Click [Add]. Leave type as "Flash". Enter ".text" for name and for the address the key thing is that this is "Atmel-speak" so the address must be in WORDS not BYTEs. You know your desired byte address is 0x3800 so half this to get the word address 0x1C00 and enter that.

The nett effect of (4) is that when the code links (avr-gcc invoked without -c) you should see that very same --section-start=.text=0x3800 that you were trying to use being passed. (in fact it will be interesting to hear how this differs from your attempt - maybe you had it on the compile rather than the link?)

Cliff

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

Thanks you Cliif,

About 2)
I usually use the DW to program my devices when they only support DW (not JTAG mode like the Mega168). I have never been able to program or change the fuses with the ISP mode. I use a STK-600 to do that. Am I suppose to be able to program or set the fuses on a Mega168 with ISP?

3) That's what I've done, but because I had a hard time loading the program at the bootloadwr section, I though it could be an issue.

4) I do not have the set up here tonight, I will come back on it but now it works but I remenber that I saw the --section-start=.text=0x3800 after compiling. Is it in the complie or link section, I don't know.

Now I need to load some pages through spi (from RF an device, SI4432) and reprogram the Mega168. I may have more questions!

Thanks for your reply!

Dominic

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

2) yes, if in the connection box of AVR Studio for JTAGICEmkII you set the mode to "ISP" rather than "JTAG" then it should operate pretty much as any standard ISP programmer using the ISP pinout given in the user manual which rather confusingly refers to it as SPI rather than ISP (yes it's a form of SPI but it's usually called ISP because it may use different pins to an AVR's normal SPI). Table 3-3 shows which 6 wires from the "squid" cable to connect to the ISP header of the board being programmed:

JTAGICE mkII probe Target pins Squid cable colors SPI pinout 
Pin 1 (TCK)        SCK         Black              3 
Pin 2 (GND)        GND         White              6 
Pin 3 (TDO)        MISO        Grey               1 
Pin 4 (VTref)      VTref       Purple             2 
Pin 5 (TMS)                    Blue   
Pin 6 (nSRST)      RESET       Green              5 
Pin 7 (Vsupply)                Yellow   
Pin 8 (nTRST)                  Orange   
Pin 9 (TDI)        MOSI        Red                4 
Pin 10 (GND)                   Brown 

Cliff

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

So does the "non-commercial" part of the FAQ Creative Commons license mean I can't reference this FAQ for building my commercial application or I can't take the FAQ and resell it or any of its information for profit?

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

If you are an author of a bootloader Brad and I hope that after reading this you'll have a better idea of how to go about it. Why would you need to either quote passages from the document or even attempt to sell bits of it simply to ship a device that contains a bootloader that has been authored as a result of the guidance here?

As it happens, for the parts I wrote you are welcome to use them freely and openly (I'm against restrictive licences like GPL and such myself and much prefer BeerWare/Free BSD etc). For other parts you'd need to contact Brad Schick to ask his permission. He no longer visits Freaks (AFAIK) but I can email him on your behalf and ask him to contact you if you want to PM me your email address.

(a PM to his ID here may trigger an email to him anyway)

Of course none of this precludes the copyright requirements of Atmel's Tutorial Forum which are given in the sticky at the top of this forum:

Tutorial Copyright

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

clawson wrote:
Why would you need to either quote passages from the document or even attempt to sell bits of it simply to ship a device that contains a bootloader that has been authored as a result of the guidance here?
Thanks for the reply.

I'm no licensing expert and was just curious if the licensing was meant to prohibit development of commercial software based on the FAQ or just copying all or part of the text as part of commercial documentaion (the latter of which I have no intention of doing).

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

Oh no, I don't know about Brad but personally I see a LOT of similar questions cropping up here about bootloaders - often about code positioning and often about function sharing between the two halves and when Brad took the time out to try and nail some of these questions once and for all and then asked myself and others to contribute further questions and comment on/correct what he'd wrote I welcomed it in the hope that many times we could now just say "read the bootloader FAQ" rather than writing out the same --section-start=0xNNNN thing for the 1000'th time.

EDIT 1363 downloads of the .PDF suggest a bit more than 1,000 in fact!

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

Quote:
That flag specifies the starting byte address of the bootloader. You can find this value in the datasheet for your AVR. Make sure you use the byte address and not the word address (most Atmel datasheets list word addresses for flash regions, but some list byte addresses).

How to recognize byte address and word address?
And how to transform a word address to a byte address ?

Thanks

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

Quote:

How to recognize byte address and word address?

Generally, you cant discern a byte address from a word address. You just need to know the context when reading: Eg, by knowing that Atmel likes to use word addresses in most cases. Or by recognizing something you know the address of (and the actual address used is double or half of that). Etc...

Quote:
And how to transform a word address to a byte address ?

Multiply by 2 (or shift left one position, if you prefer).

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

You know that the four BOOTSZ1:0 are going to select a region within 4K of the end of the chip. So take a mega328 as an example. You and I know that this has 32K BYTES of code flash. Atmel would tell you that it can hold 16K opcodes because they are 16bit WORDS. An Atmel Word is 16bits so if you talk about addressing in Words rather than 8bit bytes you halve the address. Thus the word address 0x1F27 is byte address 0x1F27*2 = 0x3E4E

Now if you dig out the 328 datasheet and look at the table that sets out the four BOOTSZ combinations. It shows:

BOOTSZ1 BOOTSZ0  Boot Reset Address (start BLS)
   1       1             0x3F00
   1       0             0x3E00
   0       1             0x3C00
   0       0             0x3800 (default)

But wait a minute, you, I and GCC think it terms of bytes, not words when talking about memory sizes and addresses. We know the 328 has 32K bytes and 32K in hex is 0x8000 with addresses 0x0000 to 0x7FFF. Yet those Atmel listed addresses are down around the 0x3??? range. So they cannot be anywhere near the last 4K of the chip as we expect BOOTSZ to be. So they must be words. So to convert to bytes double them:

BOOTSZ1 BOOTSZ0      Address (words)      Address (bytes)
   1       1             0x3F00            0x7E00 = 31.5K
   1       0             0x3E00            0x7C00 = 31K
   0       1             0x3C00            0x7800 = 30K
   0       0             0x3800            0x7000 = 28K

Obviously this example applies to a 32K AVR but I guess you can see the way to interpret things for any size of AVR. Consider it's size in bytes as a hex value. If the BOOTSZ positions you are looking at appear to be half these values they are words and need to be doubled. Use the resulting byte addresses with GCC.

NOTE: If you use AVR Studio and under "Configuration Options" need to specify a memory section address (such as positioning .text to the BLS address) then being Atmel it uses WORD addresses so for the 328 and BOOTSZ=10 you would specify 0x3E00 though when the code is built by WinAVR(gcc) you will note that it's actually 0x7C00 that is passed because Atmel know to double the value before passing it to GCC.

Cliff

Pages