Spent a while searching for guidance on this and could not find much. So I'm posting here hoping it helps others.
I am going to attempt to dump the contents of a parallel flash chip that works at 3.3v logic levels. The absolute maximum for these chips is Vcc = 4V, pins = Vcc + 0.5V. So, the 5V the Arduino is running at will wreck the flash chip. The ATMEGA2560 exits in a couple of speed grades. The plain 2560 is spec'd to run at 16MHz as low as 4.5V
The V variant maxes out at 8MHz, but will operate down to 1.8V, with a speed reduction.
The Arduino MEGA boards have the plain 2560, but YOLO. I need 3.3V and don't have a 2560V. Sticking well within the Safe Operating Area is the best chance of getting something working.
The Arduino MEGA board has a 16MHz crystal, and the 2560 can operate with an 8MHz internal oscillator. The internal oscillator is not as accurate as a crystal, which I read can cause issues with UART timing. It would also be good to push further into the safe operating area considering we're not using a V variant.
Like most AVRs, the 2560 has a System Clock Prescaler, which normally operates at 1
This prescaler can be set to factors that allow us to retain the 16MHz crystal, but achieve clock frequencies below 8MHz
However, setting this register is a little annoying to set in software, it would be better to do it permanently. Fortunately, there is a fuse bit we can set that divides the clock by 8
We can set that bit with an ISP programmer. You can quite easily look at the tables and convert to hex values, but there is an excelent online tool for doing this which is fantastic while you are working out the process. It helps you get it right first time. https://www.engbedded.com/fusecalc/
I used an Arduino UNO as an ISP programmer
https://support.arduino.cc/hc/en-us/articles/4841602539164-Burn-the-bootloader-on-UNO-Mega-and-classic-Nano-using-another-Arduino
Note: The capacitor is absolutely required, else the programmer resets and you get the 'programmer not responding' error.
To get the current state of the fuses, we use avrdude. It is included in the IDE, but it was complaining of missing a config file (it must be stored elsewhere and passed the path by the IDE). I found the easiest thing to do was just to grab the latest release, unzip to a folder, then open a command line to that folder.
https://github.com/avrdudes/avrdude/releases
In my examples, I just unzipped it all into my downloads folder.
To test its working:
avrdude -c arduino -p m2560 -P COM5 -b 19200 -v
which is
avrdude -c <programmer> -p <target MCU model> -P <The COM port its on> -b <baudrate> -v <verbose output>
C:\Users\EliteBook2570p\Downloads>avrdude -c arduino -p m2560 -P COM5 -b 19200 -v
Avrdude version 8.1
Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS
System wide configuration file is C:\Users\EliteBook2570p\Downloads\avrdude.conf
Using port : COM5
Using programmer : arduino
Setting baud rate : 19200
AVR part : ATmega2560
Programming modes : SPM, ISP, HVPP, JTAG
Programmer type : Arduino
Description : Arduino bootloader using STK500 v1 protocol
HW Version : 2
FW Version : 1.18
Topcard : Unknown
AVR device initialized and ready to accept instructions
Device signature = 1E 98 01 (ATmega2560)
Avrdude done. Thank you.
To get the fuses, we read the memory addresses using the -U command.
C:\Users\EliteBook2570p\Downloads>avrdude -c arduino -p m2560 -P COM5 -b 19200 -U lfuse:r:-:h -U hfuse:r:-:h -U efuse:r:-:h
Processing -U lfuse:r:-:h
Reading lfuse memory ...
Writing 1 byte to output file <stdout>
0xff
Processing -U hfuse:r:-:h
Reading hfuse memory ...
Writing 1 byte to output file <stdout>
0xd8
Processing -U efuse:r:-:h
Reading efuse memory ...
Writing 1 byte to output file <stdout>
0xfd
Avrdude done. Thank you.
These commands mean:
-U <Address>:<r=read, w=write>:<destination -=stdout>:<format h=hex>
Note: Setting the baudrate appears to be required, and the correct setting is in the Arduino ISP sketch at line 144:
// Configure the baud rate:
#define BAUDRATE 19200
// #define BAUDRATE 115200
// #define BAUDRATE 1000000
Putting these into the online tool
shows us what is currently set
Here, we can set the changes. I am going to select CKDIV8 to divide the clock by 8.
Pre-empting one issue I had, I Deselect BODLEVEL1 and select BODLEVEL0. The BODLEVEL change is to change the Brown-Out Detection (BOD) level to the lowest level, 1.8V. By default, it is set to 2.7. Brown out detection resets the chip if Vcc goes below the set level. And, 3.3V gives us less headroom. Deselecting all BOD bits disables BOD, but I had issues where the chip would not boot on power up (It would after reset was pressed). So, setting it to 1.8V gives us enough overhead and has the chip booting OK.
The new HEX values for the fuse bytes are then displayed.
to write them, run the avrdude command with write instead of read arguments
C:\Users\EliteBook2570p\Downloads>avrdude -c arduino -p m2560 -P COM5 -b 19200 -U lfuse:w:0x7f:m -U hfuse:w:0xD8:m -U efuse:w:0xfe:m
Processing -U lfuse:w:0x7f:m
Reading 1 byte for lfuse from input file 0x7f
Writing 1 byte (0x7F) to lfuse, 1 byte written, 1 verified
Processing -U hfuse:w:0xD8:m
Reading 1 byte for hfuse from input file 0xD8
Writing 1 byte (0xD8) to hfuse, 1 byte written, 1 verified
Processing -U efuse:w:0xfe:m
Reading 1 byte for efuse from input file 0xfe
Writing 1 byte (0xFE) to efuse, 1 byte written, 1 verified
Avrdude done. Thank you.
Here:
-U <Address>:<w=write>:<source data>:<format m=??>
(I am not sure why you use 'm' instead of 'h')
Now, the chip is running at 2MHz with a lower BOD voltage. But, it is impossible to flash using the Arduino IDE because the baudrates will now be a factor of 8 out. And if it did flash, timings for things like delay() will be a factor of 8 out. To fix this, we make a custom board.
Navigate to where the board header files are. There is a list of folders, one per board model, with 'pins_arduino.h' inside. On my PC the path is:
C:\Users\EliteBook2570p\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\variants\
Copy the existing mega folder and name it something unique. I called it mega-2Mhz
There is no need to change anything inside the .h file.
Next, find the boards.txt file. On my PC the path is:
C:\Users\EliteBook2570p\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\boards.txt
Here, there is a list of all the boards, their names, their CPU frequencies ect. Scroll down untill you find the entry for the Arduino Mega.
##############################################################
mega.name=Arduino Mega or Mega 2560
mega.vid.0=0x2341
mega.pid.0=0x0010
mega.vid.1=0x2341
mega.pid.1=0x0042
mega.vid.2=0x2A03
mega.pid.2=0x0010
...
Copy that section of the file (All the lines that begin with mega., and the associated comments) and paste a copy below (Or, at the bottom of the file).
In the new, duplicated section, change the lines so that instead of starting with mega., they start with the name of the folder we made earlier. In my case, I change mega. to mega-2MHz.
Change the line 'mega.name' to something unique. This is what will show in the 'Boards' menu. I used:
mega-2MHz.name=Arduino Mega or Mega 2560 @ 2 MHz
Change the low fuse byte from 0xFF to what we set earlier, 0x7F
mega-2MHz.bootloader.low_fuses=0x7F
Change the CPU frequency from 16000000L to 2000000L
mega-2MHz.build.f_cpu=2000000L
Change the other fuse bits in the 2560 section to what we set earlier. Extended fuses change from 0xFD to 0xFE (we didn't change the high fuse bits)
mega-2MHz.menu.cpu.atmega2560.bootloader.high_fuses=0xD8
mega-2MHz.menu.cpu.atmega2560.bootloader.extended_fuses=0xFE
IMPORTANT: The upload baudrate needs to be set 1/8 the speed of the listed upload speed, to match the CPU speed which is now running at 1/8 of its original speed. Originally, the baudrate is 115000. This needs to be set to 115000/8 = 14400. This is not a 'standard' UART speed, but it seems to work and through trial and error, this was the only setting that allowed uploading of sketches.
mega-2MHz.menu.cpu.atmega2560.upload.speed=14400
I suppose the settings for the 1280 can be left alone as we are not using that CPU, but in case, I have calculated what they should be.
mega-2MHz.menu.cpu.atmega1280.upload.speed=7200
mega-2MHz.menu.cpu.atmega1280.bootloader.high_fuses=0xDA
mega-2MHz.menu.cpu.atmega1280.bootloader.extended_fuses=0xFE
The full section with the changes then looks like this: (at least with my version of Arduino IDE)
##############################################################
mega-2MHz.name=Arduino Mega or Mega 2560 @ 2 MHz
mega-2MHz.vid.0=0x2341
mega-2MHz.pid.0=0x0010
mega-2MHz.vid.1=0x2341
mega-2MHz.pid.1=0x0042
mega-2MHz.vid.2=0x2A03
mega-2MHz.pid.2=0x0010
mega-2MHz.vid.3=0x2A03
mega-2MHz.pid.3=0x0042
mega-2MHz.vid.4=0x2341
mega-2MHz.pid.4=0x0210
mega-2MHz.vid.5=0x2341
mega-2MHz.pid.5=0x0242
mega-2MHz.upload_port.0.vid=0x2341
mega-2MHz.upload_port.0.pid=0x0010
mega-2MHz.upload_port.1.vid=0x2341
mega-2MHz.upload_port.1.pid=0x0042
mega-2MHz.upload_port.2.vid=0x2A03
mega-2MHz.upload_port.2.pid=0x0010
mega-2MHz.upload_port.3.vid=0x2A03
mega-2MHz.upload_port.3.pid=0x0042
mega-2MHz.upload_port.4.vid=0x2341
mega-2MHz.upload_port.4.pid=0x0210
mega-2MHz.upload_port.5.vid=0x2341
mega-2MHz.upload_port.5.pid=0x0242
mega-2MHz.upload_port.6.board=mega
mega-2MHz.upload.tool=avrdude
mega-2MHz.upload.tool.default=avrdude
mega-2MHz.upload.tool.network=arduino_ota
mega-2MHz.upload.maximum_data_size=8192
mega-2MHz.bootloader.tool=avrdude
mega-2MHz.bootloader.tool.default=avrdude
mega-2MHz.bootloader.low_fuses=0x7F
mega-2MHz.bootloader.unlock_bits=0x3F
mega-2MHz.bootloader.lock_bits=0x0F
mega-2MHz.build.f_cpu=2000000L
mega-2MHz.build.core=arduino
mega-2MHz.build.variant=mega
# default board may be overridden by the cpu menu
mega-2MHz.build.board=AVR_MEGA2560
## Arduino Mega w/ ATmega2560
## -------------------------
mega-2MHz.menu.cpu.atmega2560=ATmega2560 (Mega 2560)
mega-2MHz.menu.cpu.atmega2560.upload.protocol=wiring
mega-2MHz.menu.cpu.atmega2560.upload.maximum_size=253952
mega-2MHz.menu.cpu.atmega2560.upload.speed=14400
mega-2MHz.menu.cpu.atmega2560.bootloader.high_fuses=0xD8
mega-2MHz.menu.cpu.atmega2560.bootloader.extended_fuses=0xFE
mega-2MHz.menu.cpu.atmega2560.bootloader.file=stk500v2/stk500boot_v2_mega2560.hex
mega-2MHz.menu.cpu.atmega2560.build.mcu=atmega2560
mega-2MHz.menu.cpu.atmega2560.build.board=AVR_MEGA2560
## Arduino Mega w/ ATmega1280
## -------------------------
mega-2MHz.menu.cpu.atmega1280=ATmega1280
mega-2MHz.menu.cpu.atmega1280.upload.protocol=arduino
mega-2MHz.menu.cpu.atmega1280.upload.maximum_size=126976
mega-2MHz.menu.cpu.atmega1280.upload.speed=7200
mega-2MHz.menu.cpu.atmega1280.bootloader.high_fuses=0xDA
mega-2MHz.menu.cpu.atmega1280.bootloader.extended_fuses=0xFE
mega-2MHz.menu.cpu.atmega1280.bootloader.file=atmega/ATmegaBOOT_168_atmega1280.hex
mega-2MHz.menu.cpu.atmega1280.build.mcu=atmega1280
mega-2MHz.menu.cpu.atmega1280.build.board=AVR_MEGA
##############################################################
This gives a new listing in the boards menu:
Uploading blink reveals that uploads work and that the Arduino libraries are correcting for the slower CPU clock. Blink frequency is still one Hz
The LED is pretty dim at 3.3V, but still visible.
NOTE: When supplying 3.3V power to the board, do it on the '5V' pin. Putting it on Vin passes the current through a 5V linear regulator, leading to a voltage drop of of up to 1V. Putting it on the '3.3V' pin puts it on the wrong side of a 3.3V linear regulator. The '5V' pin is connected directly to the ATMEGA's Vcc pin.












