AVR231 Bootloader without UART (wireless)

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

I want to use the AV231 bootloader (version ported to gcc), except send the data over a wireless interface (Nordic NRF24L01) instead of a UART.

Instead of sending data one byte at a time, I think performance would be much better if I use the maximum RRF24L01 frame size of 32 bytes to send 32 bytes at a time at 1 Mbs.

So, that means I'll have to modify the pc code that creates the encrypted flash/eeprom records from Intel hex code format, the pc code that sends that data to the Atmega328p, and the bootloader code that receives the data and writes the flash/eeprom.

The pc code calculates a maximum frame size based on the page size of the target device. For an Atmega328p, it's 75--larger than the maximum NRF24L01 frame size. 16 byte records are added to the frame until the frame (including overhead) would exceed 75 bytes. When that happens, the frame is sent and a new frame is created.

So, I could do hack something like encapsulate the frame data in something that allows reassembling the frame from 32 byte chunks. That way, frames could be reconstructed to look exactly like they would have looked after reception by UART and reconstruction.

But, a simpler implementation might set the maximum frame to 32 in OutputWriter::OutputWriter (outputwrite.cpp line 391).

I'll keep studying the code, but there's a lot to digest. I was hoping someone who's already familiar with the bootloader could tell me if I'm going down the wrong path. For example, maybe the instructions in the AVR that program the flash only work on an entire 64 byte page instead of the 16 byte encrypted records that the frames contain.

In other words, is the maximum frame size just a maximum set for optimal performance and smaller frame sizes would work at the expense of some performance?

Thanks,

Dave Thomas

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

Also, before someone asks why I want to use wireless--it's not for performance reasons.

The wireless interface already exists on the custom pcb. So, rather than require extra hardware for a UART (or USB interface) and cabling,it would be lower cost and a better user upgrade experience to use the existing hardware for updating the firmware.

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

Byte versus word confusion...

I added a line of code in the create program to write un-encrypted records to a file. That makes it easy to see what happens if I reduce the maximum frame size to something less than the atmega328P page size.

First I let the program calculate the frame size based on the atmega328 page size (64 words/128 bytes).

The file consists of:

type 3 (FLASH Page Data) and
type 4 (FLASH Page Program)

See page 18 of AVR231 app note, but the type 3 record has 128 bytes of data and the NB field of the records (0x80) are consistent with the defintion documented in the app note, i.e. NB is the length in bytes.

However, the type 4 record associated with each type 3 record has an NB field of 64 (0x40)--like maybe this field is the length in 16 bit words, instead of bytes. However, the doc clearly states the NB field for the type 4 record is "LENGTH in BYTES".

Is this an error in the doc, or is something else going on?

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

Answering my own question--

Since the loader uses the NB field in type 4 records to control how many SPM instructions get executed, and SPM writes two bytes, that field is number of words, not bytes.

The documentation seems incorrect.

I feel lucky to even notice words versus bytes when dealing with flash memory--I wouldn't have if not for reading other posts on the web site (Thanks Clawson!). Add to that what seems like doc errors, no wonder confusion exists.

I

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

And, defining framesize to be 32 wrt the AVR page size doesn't work.

So, I'll fragment frames into multiple 32 byte "sub-frames" on the pc side and reassemble in the avr bootloader code.

Might also eliminate the CRC bytes and checks since the Nordic hardware does that along with retry mechanisms.

If anyone's interested let me know and I'll let you know how it works out

Last Edited: Sun. Aug 31, 2014 - 10:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And, defining framesize to be 32 wrt the AVR page size doesn't work.

So, I'll fragment frames into multiple 32 byte frames on the pc size and reassemble in the avr code.

Might also eliminate the CRC bytes and checks since the Nordic hardware does that along with retry mechanisms.

If anyone's interested let me know and I'll let you know how it works out

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

I'm getting close (I think)--the wireless bootloader is "kind-of working".

 

It works fine when I don't encrypt the data--everthing gets downloaded to the target processor, the flash gets programmed.  I haven't yet bothered to get the wdt stuff going that actually transfers control to the application code.

 

I'm using the pc side tools gentemp and create from the AVR231 app note unmodified.  I hacked the update PC tool to use a wireless interface to the the target Atmega328p card instead of simply sending data to a serial interface.

 

Similarly, on the Atmega side, I've hacked the loader.c code to receive from the NRF24L01 wireless chip instead of a UART.  

 

I don't think I've modified anything in the encrypt/decrypt functions.  But when I specify enrcyption by having key definitions in the configuration file, the first decrypted bytes (signature) don't match what was encrypted.

 

I don't see a straightforward way to debug the actual encryption/decryption code.  I was expecting that part to work "as is".  Suggestions for how to debug would be greatly appreciated! 

 

Has anyone used the AVR_231 code ported to GCC that's a project on this forum for a 328p using gcc?  Or any other target processor? 

 

Maybe it only works with CRC enabled, or something other than 256 bit encryption, so I'll try all combinations next.

 

Thanks,

 

Dave Thomas

 

 

 

 

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

I think this has already been done:

http://hackaday.com/2014/03/07/u...

 

I have no special talents.  I am only passionately curious. - Albert Einstein

 

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

Thanks for the link--but I'mnot surprised that it's been done.  It shouldn't be that hard, given the AVR app note as a starting point.

 

I don't think that code will work for my hardware--just want to get the AVR231-gcc working.

 

Dave Thomas

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

 

I and others have implemented wireless remote reprogramming. Mine is for this board that has a mega328p, choice of wireless radio type, RTC, megabytes of SPI Flash...

http://www.anarduino.com/miniwir...

using RFM69 radio. Low cost. AES built into the radio

Special bootloader, 1KB, that can use serial port as usual, but also re-flash the AVR's program memory based one of many program images stored in the flash chip.

see also

https://www.youtube.com/watch?v=...

for protocols, etc.

 

Last Edited: Sat. Sep 20, 2014 - 06:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I didn't mean to ask if anyone had implemented a wireless bootloader.  That's now working fine for me, both using a pc to create download files and integrated into an RPI application that allows customers to update the firmware in the system which includes the RPI and Atmega--no pc required.

 

My question was specifically whether someone had successfully used the  AVR 231 code ported to GCC that's a project on this forum.  More specifically, did the AES encryption/decryption work. That's the part that's no working yet for me. 

 

Dave Thomas

 

 

Last Edited: Sat. Sep 20, 2014 - 10:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The encrypt/decrypt part is working now.

 

The code can optionally do a CRC check of all the flashed code.   I'd been running without that option enabled, figuring that would let me start how simpler.

 

When I enabled CRC in the create configuration file, I got an error message during creation of the encrypted file.   The message was telling me the code I was trying to bootload wouldn't fit.  Something like address overlap.

 

For a testcase, I'd just grabbed a hex file that was laying around.   With the large size I've allocated for the bootloader, the testcase was too big for application memory.

 

I didn't expect using something too big would mess up the first frame's encrypted signature bytes.

 

Without CRC enabled, the message didn't occur.  So, maybe when I was using that big file, even the first frame's encrypted signature was different than expected by the loader code.

 

Either that, or I'd somehow messed up getting the right header files from the create process into the bootloader code.

 

Using a smaller hex file,  encrypted code is now successfully downloaded and flashed on the target Atmel 328p.  

 

Now I just have to get the wdt figured out.    After downloading and flashing memory (and getting a RESET record), the AES231 bootloader just spins waiting for WDT timer expiration.  When the timer expires, the CRC check is preformed.  If the CRC is good, control is transferred to the application code.

 

I've commented out the line of code that enabled the wdt, since it messes things up while debugging.   In fact, it seems like, if enabled, when the WDT expires I can no longer start/stop execution with the dragon.  The only way I can start debugging again is to disconnect power from the target and the Dragon and start over.

 

I want to enable the WDT and step through the WDT ISR code so I can really understand it well, but so far I can't find the ISR code for the wdt anywhere in the AVR231_gcc code.   

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

Looking more closely at bootldr.c, here's how I think it's supposed to work.  If anyone's familiar with the code, I'd appreciate confirmation or correction in this interpretation...

 

Apparently the wdt is configured for system reset mode--I don't see anywhere WDIE is set.  I can't find anything in the documentation that says the wdt fuse is set, so I'm assuming it should not be.

 

So, after downloading, decrypting, and flashing the application code the wdt expires and a system reset occurs.  This will cause the loader() function to be run again if the PD2 input is still low. 

 

This time the loader will sit waiting for frames, since there's nothing sending them.  The wdt will time out again, causing a second system reset.  This will continue to occur until the PD2 input is high.

 

When the PD2 input is high, the CRC check will be performed (if CRC check is enable) and the code will jump to 0x0--which is the expected location of the application code.

 

I'm thinking I want some eeprom location to control whether the bootloader loads code or jumps to the application, call it "loadCode".  The application code will set  the "loadCode" flag whenever the user wants to update the firmware.  

 

So, in the first few lines of bootload code, the loadCode flag is checked.  If set, the loader is executed, otherwise control is passed to the application code.