This part is about the _real_ `ATmega328P`, with 32 KB of flash, running our Arduino programs/sketches. In the Uno R3 case, `ATmega328P` does not interact directly with our computer (no USB support), but uses UART communication via the `ATmega16U2` supporting USB (`ATmega328P` (UART) ↔ `ATmega16U2` (USB) ↔ our computer). The `ATmega328P` uses a minimalist bootloader called `optiboot`, which is slightly under 512 bytes, leaving more space for our programs/sketches, and allows UART flashing via the `ATmega16U2`. > [!note] > You can find information about `ATmega16U2` on the Arduino Uno R3: [Arduino Uno R3 - ATmega16U2 (for USB to serial and its DFU)](Arduino%20Uno%20R3%20-%20ATmega16U2%20(for%20USB%20to%20serial%20and%20its%20DFU).md) You can find original `optiboot` bootloader in : - `%localappdata%\Arduino15\packages\arduino\hardware\avr\<version>\bootloaders\optiboot` - https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/optiboot Ressources used are available on: https://github.com/gentilkiwi/attachments/tree/main/blog/arduino_uno_r3/atmega328p Our Arduino Uno R3 uses `optiboot_atmega328.hex` file, by default in its version `4.4`. With default fuses values, the memory map for Intel HEX files is: | Start | End | Size | Section | Contents | |------------|------------|-----------|----------------------|-----------------------------------| | `0x000000` | `0x007fff` | 32 KB | Flash (_see below_) | User program + Bootloader | | `0x000000` | `0x007dff` | 31.5 KB | Flash (Program) | User program code | | `0x007e00` | `0x007fff` | 512 bytes | Flash (Bootloader) | Bootloader code | | `0x810000` | `0x8103ff` | 1 KB | EEPROM | User data | | `0x820000` | `0x820002` | 3 bytes | Fuses | Low, High, and Extended fuse bits | | `0x830000` | `0x830000` | 1 byte | Lock Bits | Protection flags | > [!note] > You can see other values in the datasheet: > - `ATmega328P` uses an addressing mode in `words` (16 bits), not `bytes` (8 bits): so bootloader start at `0x3f00` in words... but also `0x7e00` in bytes > - EEPROM is not really @ `0x810000`, as fuses or lock, but programmer softwares are using different addresses to not mix different memory areas. ## Building firmware You can build a new version of Optiboot thanks to: https://github.com/Optiboot/optiboot ``` sudo apt update sudo apt upgrade --assume-yes sudo apt install build-essential avr-libc binutils-avr gcc-avr srecord ``` ``` git clone https://github.com/Optiboot/optiboot.git cd optiboot make --directory=optiboot/bootloaders/optiboot AVR_FREQ=16000000 LED_START_FLASHES=2 atmega328 srec_info optiboot/bootloaders/optiboot/optiboot_atmega328.hex -intel ``` > [!note] > You now need an external programmer (not `arduino`) in order to replace the bootloader, see below. ## Programming > [!info] > Tested with `arduino` (with limitations), `avrispmkII` & `pickit4_isp` ### `arduino` In this mode, only flash is available (and the bootloader part is not writable). > [!note] > This is the normal programming mode used by Arduino IDE (calling an old version of `avrdude`) #### Check connection ``` > avrdude -c arduino -P COM5 -p ATmega328P -v [...] Using port : COM5 Using programmer : arduino AVR part : ATmega328P Programming modes : SPM, ISP, HVPP, debugWIRE Programmer type : Arduino Description : Arduino bootloader using STK500 v1 protocol HW Version : 3 FW Version : 4.4 AVR device initialized and ready to accept instructions Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P) [...] ``` > [!danger] > Make backup of flash before any write operation: `avrdude -c arduino -P COM5 -p ATmega328P -U flash:r:backup_flash.hex:i` > You can restore memories `avrdude -c arduino -P COM5 -p ATmega328P -U flash:w:backup_flash.hex:i` You can flash an application, such as `blink.hex`, with the following command: ``` > avrdude -c arduino -P COM5 -p atmega328p -U flash:w:blink.hex:i Reading 924 bytes for flash from input file blink.hex Writing 924 bytes to flash Writing | ################################################## | 100% 0.18 s Reading | ################################################## | 100% 0.13 s 924 bytes of flash verified ``` ### `pickit4_isp` or `avrispmkII` #### Notes >[!note] > When using a hardware programmer, connect it to the `ATmega328P` ISP connector (located at the bottom middle) > ``` > RESET CLK MISO > \---|---/ > | 5 3 1 | > | 6 4 2 | > /---|---\ > GND MOSI VCC > ``` > [!note] > When using a programmer, you can interact with fuses, lock, eeprom, and bootloader part of flash > [!note] > When using `pickit4`, you may need to switch mode to `avr`: `avrdude -c pickit4_isp -p ATmega328P -x mode=avr` (`-x mode=pic` to switch back) > [!note] > Original fuses > > | Fuse Name | Value | > |-----------|-------| > | LOW | 0xff | > | HIGH | 0xde | > | EXTENDED | 0xfd | > | LOCK | 0xcf | > > - Bootloader 256 words (512 B when in bytes), @ 0x3f00 (0x7e00 when in bytes) > - LPM and SPM prohibited in Boot Section > > You can check them with: > - version < 8.0: `avrdude -c pickit4_isp -p ATmega328P -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h -U lock:r:-:h` > - version >= 8.0: `avrdude -c pickit4_isp -p ATmega328P -U lfuse,hfuse,efuse,lock:r:-:h` #### Check connection ``` > avrdude -c pickit4_isp -p ATmega328P -v [...] Using port : usb Using programmer : pickit4_isp AVR part : ATmega328P Programming modes : SPM, ISP, HVPP, debugWIRE Programmer type : JTAG3_ISP Description : MPLAB(R) PICkit 4 in ISP mode ICE HW version : 6 ICE FW version : 1.15 (rel. 20) Serial number : BUR222474515 Vtarget : 0.0 V SCK period : 8.0 us Vtarget : 4.99 V AVR device initialized and ready to accept instructions Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P) [...] ``` #### Before flashing > [!danger] > - Make backup before any write operation: `avrdude -c pickit4_isp -p ATmega328P -U flash:r:backup_flash.hex:i` > - You can restore the flash by: `avrdude -c pickit4_isp -p ATmega328P -e -U flash:w:backup_flash.hex:i` > - if not using `-D` when writing, flash is erased (including bootloader): do not forget it, or be sure to include bootloader memory. > [!note] > The `-e` will erase the `eeprom` too (if previous fuses values were wrong, it may be not erased, feel free to check with: `avrdude -c pickit4_isp -p ATmega328P -U eeprom:r:-:h` before trying again) #### Flash Only program > [!tip] > Prefer `-c arduino` programming mode when dealing with programs only ``` avrdude -c pickit4_isp -p ATmega328P -D -U flash:w:blink.hex:i ``` Program with bootloader ``` avrdude -c pickit4_isp -p ATmega328P -e -U flash:w:blink.hex:i -U flash:w:optiboot_atmega328.hex:i ``` Program with bootloader & fuses/lock ``` avrdude -c pickit4_isp -p ATmega328P -e -U flash:w:blink.hex:i -U flash:w:optiboot_atmega328.hex:i -U lfuse:w:0xff:m -U hfuse:w:0xde:m -U efuse:w:0xfd:m -U lock:w:0xcf:m ``` or with all combined (`avrdude` version >= 8.0): ``` avrdude -c pickit4_isp -p ATmega328P -e -U flash,lfuse,hfuse,efuse,lock:w:blink_optiboot_fuses_lock.hex:i ``` > [!tip] > You can produce this combined file with fuses & lock with: > ``` > srec_cat -output blink_optiboot_fuses_lock.hex -intel ^ > blink.hex -intel ^ > optiboot_atmega328.hex -intel ^ > -generate 0x820000 0x820003 -repeat_data 0xff 0xde 0xfd ^ > -generate 0x830000 0x830001 -constant 0xcf > ``` > You can add `-generate 0x810000 0x810200 -constant 0xff ^` before the first `-generate` if you **really** want the EEPROM data (normally erased when programming) ##### New bootloader If you flashed a new Optiboot bootloader version, you can test it and see new `FW Version`: ``` > avrdude -c arduino -P COM5 -p ATmega328P -v [...] Using port : COM5 Using programmer : arduino AVR part : ATmega328P Programming modes : SPM, ISP, HVPP, debugWIRE Programmer type : Arduino Description : Arduino bootloader using STK500 v1 protocol HW Version : 3 FW Version : 8.3 AVR device initialized and ready to accept instructions Device signature = 1E 95 0F (ATmega328P, ATA6614Q, LGT8F328P) [...] ``` ## References ### Files used - gentilkiwi's GitHub: https://github.com/gentilkiwi/attachments/tree/main/blog/arduino_uno_r3/atmega328p ### ATmega / Microchip - ATmega328P: https://www.microchip.com/en-us/product/atmega328p - AVR109: Self Programming: https://ww1.microchip.com/downloads/en/Appnotes/doc1644.pdf - AVR Open-source Programmer: https://www.microchip.com/en-us/application-notes/an2568 - Serial bootloader for tinyAVR and megaAVR devices: https://microchip.my.site.com/s/article/Serial-bootloader-for-tinyAVR-and-megaAVR-devices ### SRecord - SRecord (version 1.65 used here): https://srecord.sourceforge.net/ ### Bootloaders - Optiboot: https://github.com/Optiboot/optiboot - Urboot: https://github.com/stefanrueger/urboot ### Programmers #### Hardware - Pickit 4: https://www.microchip.com/en-us/development-tool/pg164140 - AVRISP MKII : https://www.microchip.com/en-us/development-tool/atavrisp2 #### Software - AVRDUDE (version 8.0 used here): https://github.com/avrdudes/avrdude - Microchip Studio: https://www.microchip.com/en-us/tools-resources/develop/microchip-studio - MPLAB X IDE (includes IPE): https://www.microchip.com/en-us/tools-resources/develop/mplab-x-ide