I have a new atmega328p (i.e. fresh from Digi-key) and I'm wanting to use an external MEMS clock to drive it (vs. a "regular" XTAL crystal) so that I can use the pin saved for something else. I understand that in order to accomplish this I will need to reprogram the fuses. I've found the relevant code in the "boards.txt" file, here it is;
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328P
## ---------------------------------------------------
pro.menu.cpu.8MHzatmega328=ATmega328P (3.3V, 8 MHz)
pro.menu.cpu.8MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.8MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328.upload.speed=57600
pro.menu.cpu.8MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.8MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.8MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
pro.menu.cpu.8MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328.build.f_cpu=8000000L
It looks like in order to use an external clock the lower nibble of the lower fuse byte has to be set to 0x0 ... so I'm tempted to modify the board file to change the low_fuses setting to 0xF0, like this;
## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328P
## ---------------------------------------------------
pro.menu.cpu.8MHzatmega328=ATmega328P (3.3V, 8 MHz)
pro.menu.cpu.8MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.8MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.8MHzatmega328.upload.speed=57600
pro.menu.cpu.8MHzatmega328.bootloader.low_fuses=0xF0
pro.menu.cpu.8MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.8MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
pro.menu.cpu.8MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.8MHzatmega328.build.f_cpu=8000000L
As long as my board that contains my new atmega328p has the MEMs oscillator also loaded, can I kill two birds with one stone in the sense of burning the bootloader (via the IDE menu using an UNO R3 as the programmer) and get the new and desired fuse values in one operation?
What I'm confused about I think (i.e. the reason for the question) is how does the blank atmega328p device know where to get it's clock from to load the code (fuse bits) necessary to tell it where to get its clock from? ... it seems like a chicken and egg scenario.
I suppose the atmega328p could start-up using it's internal oscillator and then switch (if necessary) to the clock source as specified by the fuse bits immediately following the programming completion of the lower-byte fuse settings ... or wait until it receives a reset (after bootload programming completes) before it operates using the new fuse settings?
I'd be very happy with just a straight answer to my original question, but if anyone could educate me on the proper way to think about the process, I might be in a position to answer my own question.
TimHo:
It looks like in order to use an external clock the lower nibble of the lower fuse byte has to be set to 0x0 ... so I'm tempted to modify the board file to change the low_fuses setting to 0xF0, like this;
I don't think you have the fuse setting correct. You can see here that low fuse of 0xF0 is associated with "Undefined Preset 4: 0x30 0b00100000":
What might be confusing is that fuse bit value of 0 is "programmed", while a fuse bit value of 1 is "unprogrammed". This leads people to sometimes invert their fuse bit values. In fact I just saw this issue cause someone to set their fuses to one of these "undefined presets" and possibly brick some chips: http://forum.arduino.cc/index.php?topic=602107
TimHo:
As long as my board that contains my new atmega328p has the MEMs oscillator also loaded, can I kill two birds with one stone in the sense of burning the bootloader (via the IDE menu using an UNO R3 as the programmer) and get the new and desired fuse values in one operation?
That's correct. The Arduino IDE's Tools > Burn Bootloader actually does two things: Set fuses according to the definitions in boards.txt for the currently selected board, and flash the bootloader to the chip.
There are a couple things you should be aware of:
There may be multiple copies of the Arduino AVR Boards boards.txt on your computer. Only one of these is actually in use. If you are editing the wrong file, that could result in some confusion. The easiest way to find the active Arduino AVR Boards location is as follows:
Select an Arduino AVR Boards board from the Tools > Board menu
File > Examples > SPI > BarometricPressureSensor (or any other SPI example sketch)
Sketch > Show Sketch Folder
Move up folder levels until you reach the one that contains boards.txt
After editing and saving boards.txt, you need to restart the Arduino IDE before the changes will take effect.
TimHo:
What I'm confused about I think (i.e. the reason for the question) is how does the blank atmega328p device know where to get it's clock from to load the code (fuse bits) necessary to tell it where to get its clock from? ... it seems like a chicken and egg scenario.
By default, the chip comes from the factory set to use the internal oscillator. That is the only sensible setting. If it was set to use an external clock by default, people who wanted to use the internal oscillator in their application would need to connect a clock source just to be able to set the fuses.
The exception to this is the chip you will find sold as "With Arduino Bootloader" these have had their fuses set according to the Arduino Uno's board definition, and so will require an external clock source to be used.
@Pert ... I think I have perhaps bricked my atmega328p .... but I don't understand how I managed to accomplish that, I still think I'm perhaps missing a fundamental understanding regarding the process. Allow me to try to state my understanding, perhaps you might interject as I go wrong?
I think I have figured out the correct fuse setting, if all I wanted to do was take a standard 3V Pro Mini bootloaded device and convert it from an 8MHz external crystal to an 8MHz external clock source (apples to apples in every other functional sense) I would need to re-program the low fuse byte from "0xFF" to "0xE0".
I recognize (now) that my virgin atmega328p came with lower byte fuse setting "0x62" which translates (AVR® Fuse Calculator – The Engbedded Blog) to the 8MHz internal oscillator.
It also makes sense (now) that therefore;
If it was set to use an external clock by default, people who wanted to use the internal oscillator in their application would need to connect a clock source just to be able to set the fuses.
... and so from this I'm recognizing (I believe) that the process of programming the bootloader requires the presence of a timing signal connected to the target device (whether that be the internal oscillator, external oscillator (XTAL) or external clock) that is consistent with the fuse settings at that time?
So I think it follows that after I have taken my virgin atmega328p and programmed it to have the bootloader consistent with a 3V Pro Mini ... that, in order to subsequently re-program the device with another bootloader/fuse setting so as to now change it to an external clock (i.e. low byte from 0xFF to 0xE0) my target atmega328p at this point would need to have an 8MHz external crystal connected to it in order to re-program the bootloader/fuses to something else .... because the fuse settings at this point are specifying an external 8MHz crystal and the physical configuration of the target with respect to where it gets its timing signal must be consistent with the programmed fuse settings?
So if all the above is correct, I don't see how I managed to brick by atmega328p, but I suspect that is exactly what I did because avrdude is reporting the following;
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin>avrdude -C C:\avrdude.conf -c avrisp -p m328p -P com6 -b 19200 -U lfuse:r:-:i -v
avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\avrdude.conf"
Using Port : com6
Using Programmer : avrisp
Overriding Baud Rate : 19200
AVR Part : ATmega328P
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC2
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff
flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : STK500
Description : Atmel AVR ISP
Hardware Version: 2
Firmware Version: 1.18
Topcard : Unknown
Vtarget : 0.0 V
Varef : 0.0 V
Oscillator : Off
SCK period : 0.1 us
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.03s
avrdude: Device signature = 0x000000 (retrying)
Reading | ################################################## | 100% 0.03s
avrdude: Device signature = 0x000000 (retrying)
Reading | ################################################## | 100% 0.03s
avrdude: Device signature = 0x000000
avrdude: Yikes! Invalid device signature.
Double check connections and try again, or use -F to override
this check.
avrdude done. Thank you.
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin>
Any further comments and thoughts/suggestions would be appreciated.
Many thanks,
Tim.
P.S. I'm going to get more virgin atmega328p's so that I can try again ... I will report back in any case. Thx.
P.P.S. Thanks so much for the tip on locating the correct "board.txt" file, I was indeed modifying the wrong one! That in itself saved me days and days of head scratching and frustration.
Theory and practice suggest that even if the clock is set for "external crystal", you can still get the chip to work by "injecting" a pure clock signal into the correct XIN pin. (re you sure you have the clock going to right pin?)