SparkFun has a pretty good tutorial on getting the Funnel IO card bootloader altered to something simple. I wanted some different things, though 

  1. Work with Zigbee in non-transparent mode.
  2. Work in Packet API mode with escapes.
  3. Utilize the built-in packet info

This lets me have lots of Xbee devices transmitting throughout the house while I specifically program a single device. 

This walkthrough works flawlessly in XB-24 ZB Zigbee with a Series 2. I tested at 9600,19200, and 38,400 baud (endpoint). All worked fine. 


The implementation that SparkFun goes through really has a number of steps you don’t need so I’m going to go through my process. It requires less hardware alteration and less setup. 

Hardware Changes

Solder the jumper on the Funnel IO

This jumper (see below) connects the XBee DIO3 line to the Atmega reset line – letting you software reset. 


Software Changes


Set up the two XBees


Update to the latest firmware on the two XBee’s.  X-CTU is pretty good at this. For a new XBee select 9600 baud, Hardware handshaking, and select a serial port. Switch to Modem Configuration tab then select the latest firmware. 

  1. Set the USB Explorer (master/desktop) XBee to XB24-ZB : ZIGBEE COORDINATOR API
  2. Set the Funnel IO (slave) XBee to  XB24-ZB : ZIGBEE END DEVICE API

After you select the modem and firmware type click the write button. Often XCTU will fail after writing new firmware. Ignore it and give the chip some time to recover.  When ready, do the firmware default changes below. 

Hint: Go back to the PC Settings tab and click Enable API after you program the xbee. 

Hint: you’ll find thing are much smoother if you let the XBee join the PAN before you try to download to it (or program it). This takes a couple of seconds after power-on. You can tell that from the green led on the Funnel board. 

Changes to the XBee firmware defaults

Do this with X-CTU. Ensure Always update firmware is off

  1. Select a 16 bit PAN id common to both.
  2. Select API Mode 2 (escaped) on the slave. We are sending binary data.
  3. Click the Write button.


A common PAN ID  is the simplest way to add a little security and in my experience a consistent link required a hardcoded PAN ID.  I think you can mix and match API modes so use what you want with the coordinator. I use API/Escape for symmetry. 

Reprogram the bootloader on the Funnel IO board

The bootloader is a small program that lives high in the atmega memory and at startup it checks for a bit to see if you want to reprogram the main program. If so it reads the main program via RF and writes it to eeprom. If not, it just starts the existing main program (at 0). 

Re-Writing the bootloader requires a serial (ISP) programmer. I used the AVR-ISP MKii but i’ll bet SparkFun’s works fine. I like picking things from the AVR Studio menu… 

The simplest thing to do is get a 2×3 berg connector (male/male) stick it in the end of the programmer cable then pressfit it onto the board (in the 6 pin connector near the reset button). You’re just going to program the bootloader once (you hope). 

  1. Use this hex file (and AVR Studio) to program the board. If you want to change from 9600 baud you’ll need to rebuild the c file with the def changed. 

Hex file: funnel_bootloader.hex 

C Source: funnel_bootloader.c 

Use this program to download applications to the reprogrammed funnel. Remember to set your XBee destination address. Screamer exe ( screamer.exe 

Here’s the Screamer source if you want it (C#)

We’re Done

That’s it – you don’t need anything else except the version of Screamer that uses my format (see the C code for doc) and packetizes. 

Hint: remember to go back and click “Use escape characters” in the PC Settings tab when you switch to api mode 2. 

I’m really lazy so I deliberately set the baud rate on the AVR to 9600 (XBee default) rather than the usual 19200. You can change it on the slave if you update the bootloader. In my test a large file downloaded about 30% faster at 38,400 than 9,600. Both were rock-solid. 


Resetting the Atmega

The original article did some interesting tying together of lines to reset the atmega. I just do the following to set D3 low then high (input). This resets the processor comfortably. 

//D3 low to reset for 200ms
request = new ZNetRemoteAtRequest(Dest, "D3", new int[] {4});
bResult = xCom.sendSynchronous( request, 2000);
Thread.sleep( 250);
// D3 input (pullup high) so you can click the switch
request = new ZNetRemoteAtRequest(Dest, "D3", new int[] {3});
bResult = xCom.sendSynchronous( request, 2000);

The bootloader

Things to note: 

I scratched my head as to why we were programming the EEProm at 0x00 when the bootloader was there. So I tried to run the bootloader at 0 and have it put stuff at 0x400. Nope, it ran fine but I couldn’t program the EEprom nohow. 

It turns out the program command must be in the bootloader segment to run. Nate’s makefile did this but I didn’t use it, I started with the project wizard and used his code as a base. 

The bootloader must be based at 0x3800. You can do this the easy way (run Nate’s makefile) or the hard way (modify the project). I modified the project to move the .text section to 0x1C00 which puts it in the bootloader. Online folks say to use the BOOTLOADER_SECTION define but I couldn’t get it to do anything relevant even when I moved the .bootloader section. 

  • To create an appropriate bootloader project go to Project / Configuration Options and under Memory options add a .text section at 0x1C00 (it’s in words).
    • You’ll see this
      at the start of the bootloader hex indicating it loads at 3800 if you did it right.

Packet mode has some real advantages (like automatic handshaking and easy remote xbee control).  It automatically handshakes with the sender and the odds of corrupt received data are low.  I do send an OK packet after each receipt just to enable random avr processor speeds – so there are no timing dependencies. 

Reliability Testing

I deliberately tried putting the Funnel in my kitchen, near my wireless router, and a ways from my office and it programmed flawlessly. I got no response to one AT command during the reset sequence, indicating a distance issue, but the data was flawless. 


After some changes to the Java (oops) I’ve been running absolutely flawlessly. Programmed 10-20 times in a row, rebooted, reflashed, you name it. No hassles… I just tried a large file (21K hex file) and again no issues…

Tagged with:

14 Responses to Wireless Bootloader for the Funnel IO

  1. akermi says:

    i have to program a wireless bootloader using Xbee serie2 PRO module for atmega but i have problems when using this functions to write to the flash memory.:

    void boot_write (uint16_t page, uint8_t *address)
    int i;


    // Erase page.
    boot_spm_busy_wait ();

    // Write data to buffer a word at a time.
    for (i=0; i<SPM_PAGESIZE; i+=2)

    unsigned int w = *address++;
    w += (*address++) << 8;

    boot_page_fill (page + i, w);

    // Write page.




    NB: i program my mega8 using an AVRISP mkii

    also i need to know how can i set the fuses

  2. Mark says:


    I didn’t set the fuses so I haven’t really looked at them. As far as I know, the default values (at least as shipped from Sparkfun) worked fine.

    The series 2 Pro should support virtually the same software as the non-pro and should, as far as I know, work well with the wireless bootloader. If you’re having a problem I’d be curious what the symptom is.

    The piece of code you’re looking at runs on the atmega and doesn’t really have anything to do with the XBee – since once the boot-write function is called the XBee is finished transferring a block.

    You can use whatever firmware programmer you want with the Atmega. As long as the boot firmware gets there it doesn’t really matter how.


  3. akermi says:

    how can i forse my bootloader to be installed at 0xF3FF

  4. Mark says:

    Hi, I don’t think 0xf3ff is supported on the atmega since it doesn’t have that much ram. If yours is supported there, then, as discussed in the article set the bootloader address by defining .text as 0x79FF. This is == 0xf3ff/2 (divide by 2 since it’s in hex words).

    Verify the address by checking the hex file created during the build. The address is the beginning of each hex line.


  5. akermi says:

    when i log to Project> Configurations Options> Memory Settings i can’t found how to change the .text section (i use the avrstudio4)
    thank u Mark

  6. akermi says:

    hi Mark,
    my bootloader should start at 0x1800 and not at 0xf3ff.
    i defined the .text section to start at 0x0C00 but when i built, the address in the hex line doesn’t change.

  7. akermi says:

    i used an external make file. it works fine.
    but my bootsection can’t support my hex file because it’s tooooooooooo long.
    —————> i should re-write my code.
    thank you Mark for the help

  8. Mark says:

    Hi, you’re welcome.

    That’s too bad. The bootloader I wrote (based on Nathan’s) is already starting to stress the processor – it’s at like 60% of capacity.

    Good luck.


  9. akermi says:

    i tested my bootloader, it works for atmega8 and 16.
    but when i restart my atmega for the first time, the program can’t jump to the main application. to make it work, i should restart the atmega 2 time or more. how can i solve this problem……………

  10. akermi says:

    The END!!!!!!!!!!!!!!!!!
    my program works fine
    bonne continuation

  11. John says:

    hi Mark, i tried this source code with the XBee Series 1 but it did n’t work knowing that i made the necessary changes.
    could you help me!!!!!!!!!!!!

  12. John says:

    hi Mark, i tried this source code with the XBee Series 1 but it did n’t work knowing that i made the necessary changes.
    could you help me!!!!!!!!!!!!

    • Mark says:


      The series 1 doesn’t run this firmware and I haven’t really looked into supporting it because it won’t support Zigbee. I have a few myself I’d sell cheap…

      Wish I could help.


  13. Hassan says:

    I have to realize an application in C sharp to program a microcontroller (atmega16) via serial connection.So, I have to find a bootloader and then upload it in the microcontroller using an external programmer.I tried several bootloader code.but nothing.please can you help me.thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Set your Twitter account name in your settings to use the TwitterBar Section.