My current project uses an atmega328 and will need to have updated firmware uploaded though the serial port. I figured optiboot should work fine for this, so I modified the optiboot source for an atmega328 at 8 MHz and 2400 baud (just for testing). I made an rs232 to TTL serial converter with transistors and verified that I got clean edges, burned the bootloader with an AVR dragon, and used avrdude with "-c arduino -p m328 -P COM1 -b 2400 -F -v -U ........" to upload the code. The first thing that went wrong is that the chip was recognized as an atmega328P (device signature 0x1e950f), whereas I'm using an atmega328; I probably missed something while modifying optiboot, but the chips are virtually identical so added '-F" to avrdude. After that everything went fine, but as soon as avrdude started verifying the code I got a verification error, " first mismatch at byte 0x0002 0x35 != 0x34", I tried another hex file and got a mismatch at 0x0000. Both of these upload fine with any other programmer. I've tried baud rates from 625 up to 115200 (below 2400 doesn't work at all) and I get the same exact error, so I don't think this is caused by the internal oscillator being off. I even manually set UBBR0 (the baud rate register) in optiboot to get as close to 2400 baud as I could. I've even tried uploading to an atmega328P and I get the same problems. Do you guys have any idea what could be causing these verification errors?
I know something about the signature bytes issue. Optiboot when requested by AVRDUDE for the device's signature does not actually read the values from the chip but rather just returns the bytes for a 328P. So somewhere in the Optiboot source the signature bytes are 'hardcoded' and should be easily changed and recompiled. Or just lie and tell AVRDUDE your using a 328p chip rather then a 328 non-P chip.
Yeah, that's pretty much what I figured. I guess they just wanted to save a few bytes.
bobthebanana: Yeah, that's pretty much what I figured. I guess they just wanted to save a few bytes.
Yes. Optiboots main claim to fame is that is complied down to a size to fit in the minimum allowed protected bootloader size, thereby giving back to the user a little more flash space then with the prior larger 328 bootloaders.
so I modified the optiboot source for an atmega328 at 8 MHz and 2400 baud
probably you have done something wrong in your modifications of optiboot. The changes you made shouldn't have required editing the source at all; just tweaking the makefile. Can you show us exactly what you did, what you used for the compile command(s) and how your burnt the bootloader into the chip?
I admit that I don't really know what I'm doing here and I've never messed aroud with makefiles so I thought editing the source was the way to go. Basically I just make a new project in atmel studio and threw all of the optiboot files in. Then I added
#define F_CPU 7900000L #define BAUD_RATE 2400
to the top of optiboot.c and and removed
#if (F_CPU/BAUD_RATE) > 280 // > 57600 for 16MHz #ifndef SOFT_UART #define SOFT_UART #endif #endif
to use the hardware uart.. I also changes a few of these
#elif defined(__AVR_ATmega328P__) to this
#elif (defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)) so that it would compile for a 328. After the changes I just let atmel studio compile it for me (it ends up at 766 bytes, but that's good enough for me). Here is what AS6 says it's doing to compile:
avr-gcc -funsigned-char -funsigned-bitfields -DDEBUG -O1 -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -g2 -Wall -mmcu=atmega328 -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"to link:
avr-gcc -Wl,-Map="$(OutputFileName).map" -Wl,--start-group -Wl,-lm -Wl,--end-group -Wl,--gc-sections -mmcu=atmega328and to assemble:
avr-gcc -Wa,-gdwarf2 -x assembler-with-cpp -c -mmcu=atmega328 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -Wa,-gI used my AVR dragon to burn the bootloader and to burn the BOOTSZ1, BOOTSZ0, and BOOTRST fuses. I have a feeling that the problem lies in the fuse settings, or the fact that my file is over 512 bytes, while optiboot expects itself to be less that 512 bytes (does it?). If you could provide me with a "correct" hex file for an atmega328 running at 8 MHz (7.9 to be exact) at a baud rate from 2400 to 115200 baud that would awesome.
Yes, going over 512 bytes would be a big problem... I'm surprised that it seems to work at all. In addition to being too big, there are a bunch of compile options in the makefile that you probably didn't carry over to the AS project, that are important.
If you're running 8MHz, you should probably just use the default bootloader (designed for 115200bps @16MHz) and upload to it at 57600 instead (it'll be running at half speed, and half of 1152000 is 57600.)
It looks like running at 7.9MHz will actually produce a MORE accuate 57600 than a true 8MHz...
Okay so I went ahead and burned the regular optiboot and then uploaded my code at 57600 baud. It wrote and verified properly, but it failed when trying to burn the fuses. Now for some reason the MCU seems to restart every 80 ms. WTF? I can still upload code and change the fuses with the dragon, but the code only runs for 15 ms then it does nothing for 65 ms, and then restarts. Anyway, I tried again on another chip and it works fine, but I still can't write any fuses. I probably won't need to for firmware updates though. Question now is, how do I unbrick the first chip? What in the world would cause the code to run for 15 ms, idle for 65 ms, and then restart? The watchdog is disabled if that could have anything to do with it.
There is a fuse that causes the watchdog to be turned on immediately after reset. Although when optiboot is there, it should be turning that off, regardless.
You do know that the bootloader cannot write the fuses, right? In order to set the fuses properly before using the bootloader, you need to use a device programmer of some kind to set the fuses either immediately before or immediately after your burn the bootloader (using the same tool you used to write the bootloader, probably.)
Ah, I didn't know that the bootloader couldn't write fuses, that clears it up. By "the watchdog is disabled" I meant that the watchdog fuse wasn't set, so I doubt that it's causing a problem. I guess I'll just suck this chip off and put a new one in since this has to be finished by tomorrow. I've never had a chip fail like this before though, it's quite strange.
I've never had a chip fail like this before though, it's quite strange.
Good ol' Murphy and his annoying Law!