Uploading HEX files to Barebone Atmega328P

I’m working on a project that requires uploading hex code to a barebones ATmega328P chip without being attached to a computer. I’ve followed Nick Gammons incredible “Atmega_Hex_Uploader_Fixed_Filename” instructions and I’m able to upload hex files without problems. However, my project requires a 16 MHZ clock rate (with an external crystal) and I cannot get the fixed filename uploader to make the necessary changes to stop using the internal 1 MHZ clock and start using the external 16 MHZ clock. I’m assuming that the low fuse must be changed from the factory default of 0x62 to 0xFF. The ATmega329P chips must be generic and cannot be preloaded with fuse settings or bootloaders.

I’ve spent hours searching this site, AI sites, and modifying the ATmega_Hex_Uploader_Fixed_Filename sketch with no success. Any help would be very much appreciated.

When using arduino-cli to burn the fuse bits in a 328P for a 16MHz crystal with my USBTinyISP, it sets efuse to 0xFD and hfuse to 0xD7 as well as setting lfuse to 0xF7.

The code has a function named writeFuse(), which takes an argument of the hex value for the fuse, and which fuse to write, from the keywords writeLowFuseByte, writeHighFuseByte, writeExtendedFuseByte, or writeLockByte. After writing the fuses, you likely need to call getFuseBytes() to get the fuse settings for later use when writing the hex file.

Would be glad if you write the procedures or refer to a link on how to use arduno-cli commands to burn fuse bits and sketch into an ATmega328P MCU.

Tiy can look at "optiloader", which was designed to both program fuses and a bootloader into old or new chips. Gammon's program is based on it. (Note that optiloader only works with quite small binaries - it's purpose was to easily update older Arduinos from the old bootloader to Optiboot, to get back the 1.5k of program space...

The soucre code for Atmega_Hex_Uploader_Fixed_Filename claims that it can update the fuses, but I don't quite see how you can specify the fuses you want...

And the doc shows it setting all 3 fuses:

but you have to keep reading waaaaay down to discover that it's referring to the original Atmega_Hex_Uploader, not the fixed filename loader.

Variant which uploads a single file

Following a request on the Arduino forum a modified version is now available:

arduino_sketches/Atmega_Hex_Uploader_Fixed_Filename at master · nickgammon/arduino_sketches · GitHub

This removes all serial interaction, and is now a standalone "update firmware" sketch.

The intention is to allow multiple chips to be programmed, if necessary "in the field", without needing to have a laptop or PC with a serial interface.

It would appear that neither the original Atmega_Hex_Uploader nor Atmega_Hex_Uploader_Fixed_filename does exactly what the OP is looking for. And the history in the comments of the Fixed_Filename variant include stuff that was removed when it was forked from the original.

Thanks for the information everyone. I was able to use the original “Atmega_Hex_Uploader” sketch to adjust the fuses for an externa clock and to upload my program to the chip, but you must be attached to a computer. I tried to use the fuse adjustment section of the original program and apply it to the Fixed Filename version, but without success. I believe that I’m going to throw in the towel on the Nick Gammon program (even though it works really well for certain applications) and pivot toward the Optiloader as mentioned by westfw. Hopefully I’ll be able to get that working without having to resort to forum lol.

After using this forum for many years this was the first time I made a post. Judging by the responses I received I should have done it sooner. Thanks again.

All right. I finally a) wasn't feeling completely like death warmed over after dealing with whatever respiratory bug for the past month that's been going around and just will not go away and b) had a couple of hours with nothing to do after being out hiking all afternoon. So I dove into this.

I sat down and wired myself up an Uno R3 to be a programmer for Nick Gammon's Atmega_Hex_Uploader_Fixed_Filename sketch.

I used an USBtinyISP to program the fuses in a 328P like they come from the factory.

I compiled a simple blink sketch with the clock set to 1MHz internal, and used the USBtinyISP to upload it to the 328P whose fuses I'd set for 1MHz internal.

Took that 328P, stuck it in a breadboard, and it blinked at the 1Hz frequency I'd expected. Great.

Compiled that same blink sketch with the clock set to 16MHz external. Renamed the .hex file to firmware.hex, copied that to a uSD card and put it in the uSD adapter in the Gammon programmer.

Put the 328P in the Gammon programmer, powered it up, and used it to program the blink sketch compiled for 16MHz into the 328P with its fuses set for 1MHz.

Put the 328P back in the breadboard, added a 16MHz crystal and 2x22pF caps (even though none of that was needed yet), and applied power. As expected, the LED blinked 16x slower. Glacial, in fact.

Here's where we finally get to the good stuff.

I opened up the Atmega_Hex_Uploader_Fixed_Filename sketch again and found the updateFuses routine. At the end we see this:

  if (writeIt)
    {
    writeFuse (fuses [fusenumber], fuseCommands [fusenumber]);      
    }
    
  return false;
  }  // end of updateFuses

whose sole purpose in life is to unprogram the BOOTRST fuse if needed.

Taking the quick and dirty road to a solution, I modified this bit to this:

   if( writeIt ) {
      if( currentSignature.sig[0] == 0x1E && currentSignature.sig[1] == 0x95 && currentSignature.sig[2] == 0x0F ) {
         // set 328P to 16MHz external
         writeFuse(0xF7, fuseCommands[lowFuse]);
         writeFuse(0xD7, fuseCommands[highFuse]);
         writeFuse(0xFD, fuseCommands[extFuse]);
      } else {
         writeFuse(fuses[fusenumber], fuseCommands[fusenumber]);
      }
   }

   return false;
}  // end of updateFuses

Now, if we're programming a 328P, it sets the fuses to change the clock to 16MHz external. But only if we're programming a 328P; it works exactly the same for everything else. I could have gone through the sketch and stripped out everything for all other MCUs, but that seemed like too much work for an unpaid gig on a Saturday night. :slightly_smiling_face:

I uploaded the modified sketch to the Gammon programmer, removed the 328P from the breadboard and put it in the programmer, programmed it, and returned it to the breadboard. With power applied, the firmware.hex file, that was compiled for a 16MHz clock, that was uploaded to the 328P with the fuses set for 1MHz internal, just like out of the factory, had been uploaded to the 328P, and its fuses were set for 16MHz.

And the LED blinked at the expected 1Hz rate.

So there we have it. The Gammon fixed filename uploader hacked to set the 328P's fuses to 16MHz external.

I was thinking that it shouldn't be too hard to modify the sketch to program "whatever fuses you wanted"; I'm glad you went and did it!

Mostly just a matter of finding the energy, the time, and getting a round tuit!

Thanks for the follow-up and the extra effort. I found the same infomation on Kevin Darrah YouTube post titled "AVR Standalone Programmer from SD Card". It basically adds the same code as van_der_decken. I made this modifiation to the Nick Gammon Hex file uploader and everything works perfectly now. My next step is to have a PCB manufactured and produce a very simple plug-and-play programmer. Thanks again everyone.