To figure out what the heck an arduino was and why people have been so excited about them I decided to give the hello.arduino.328p board located on the embedded programing lecture page a try. This board is nice as it uses a slightly more poweful atmega328 chip with more ram and more pins.
After making and programming the board successfully with the example code on the website I spent way to much time figuring out how to run an arduino at 20 MHz. The easy way to use this board is to simply use the internal 8MHz clock when playing with the arduino programming environment and be happy with that. For some historical reasons the arduino bootloader is only designed to run at 16MHz. If you run at 20MHz nothing particularly breaks but some of timing functions will have a little error. It is possible to manually edit the code to fix some of the error, and some of them may now be fixed in the source.
I had a further issue, in that the arduino is built to run on the atmega328p processor, and it seems that the arch shop only has the atmega328. This would make for some fun trickery down the line.
This is a bad idea. Just get a 16MHz resonator and a atmega328p.
Really
Ok... fine... I'll tell you
First you need to download the latest version of the arduino software. After doing that download the latest build of the optiboot bootloader (a snazzy bootloader that replaces the default) and replace the version of optiboot that came with the arduino software.
You can use optiboot to compile new bootloaders for the arduino. The following can be added to the optiboot makefile to add a profile for a 20MHz atmega328 device.
fabduino20: TARGET = fabduino20
fabduino20: MCU_TARGET = atmega328
fabduino20: CFLAGS += $(COMMON_OPTIONS)
fabduino20: AVR_FREQ ?= 20000000L
fabduino20: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
fabduino20: $(PROGRAM)_fabduino20_atmega328.hex
fabduino20: $(PROGRAM)_fabduino20_atmega328.lst
fabduino20_isp: fabduino20
fabduino20_isp: TARGET = fabduino20
fabduino20_isp: MCU_TARGET = atmega328
# 512 byte boot, SPIEN
fabduino20_isp: HFUSE ?= DE
# full swing (20MHz) 16KCK/14CK+65ms
fabduino20_isp: LFUSE ?= F7
# 2.7V brownout
fabduino20_isp: EFUSE ?= 05
fabduino20_isp: isp
Unfortuniately optiboot is only written to work with a select family of microcontrolers. The atmega328 is not one of them. Fortuniately the 328 is the same at the 328p except for the pico-power addons (for the most part) so you can modify the source of optiboot to work with atmega328's. Open the pin_defs.h file and any time you find a line like:
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
add the 328
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
Then from a terminal (assuming you have the avr toolpath installed already) you can build the new bootloader with:
make fabduino20
You should now have a optiboot_fabduino_atmega328.hex file in your optiboot folder. Now that we have the bootloader that we want to use, we have to tell the arduino software how to use it. Figure out where the boards.txt file is on your OS and add a board profile for the 20MHz board on a 328 (the format has changed slightly since the file that is on the MAS.816 website)
fab.name=fabduino20
fab.upload.tool=avrdude
fab.upload.protocol=arduino
fab.upload.maximum_size=32256
fab.upload.maximum_data_size=2048
fab.upload.speed=115200
fab.bootloader.tool=avrdude
fab.bootloader.low_fuses=0xF7
fab.bootloader.high_fuses=0xDE
fab.bootloader.extended_fuses=0x05
fab.bootloader.unlock_bits=0x3F
fab.bootloader.lock_bits=0x0F
fab.bootloader.file=optiboot/optiboot_fabduino20_atmega328.hex
fab.build.mcu=atmega328
fab.build.f_cpu=20000000L
fab.build.core=arduino
fab.build.variant=standard
and while you're at it add a profile for the 20MHz board on a 328p
fab20.name=fabduino20p
fab20.upload.tool=avrdude
fab20.upload.protocol=arduino
fab20.upload.maximum_size=32256
fab20.upload.maximum_data_size=2048
fab20.upload.speed=115200
fab20.bootloader.tool=avrdude
fab20.bootloader.low_fuses=0xF7
fab20.bootloader.high_fuses=0xDE
fab20.bootloader.extended_fuses=0x05
fab20.bootloader.unlock_bits=0x3F
fab20.bootloader.lock_bits=0x0F
fab20.bootloader.file=optiboot/optiboot_fabduino20_atmega328.hex
fab20.build.mcu=atmega328p
fab20.build.f_cpu=20000000L
fab20.build.core=arduino
fab20.build.variant=standard
The reason for the two profiles is because for some as of yet unexplaied reason, while buring the bootloader the chip is properly detected as a atmega328, but when trying to use the arduino software to upload a sketch over ftdi the device signature is that of a atmega328p. I suspect that this has to do with the internals of optiboot. To install the sketch ensure the fabduino20 board is selected and the proper ISP, and select tools -> burn bootloader. After buring the bootloader change to the fabduino20p board profile and you can upload sketches as normal. As I mentioned - the timing functions will be ever so slightly off, so this is not an ideal setup for time sensitive operations.
While we are at it we might as well make a profile for a 8MHz atmega328 device (using the internal oscillator). This will have proper timing. The addition tot he makefile for optiboot:
fabduino8: TARGET = fabduino8
fabduino8: MCU_TARGET = atmega328
fabduino8: CFLAGS += '-DLED_START_FLASHES=2' '-DBAUD_RATE=38400'
fabduino8: AVR_FREQ ?= 8000000L
fabduino8: LDSECTIONS = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
fabduino8: $(PROGRAM)_fabduino8_atmega328.hex
fabduino8: $(PROGRAM)_fabduino8_atmega328.lst
fabduino8_isp: fabduino8
fabduino8_isp: TARGET = fabduino8
fabduino8_isp: MCU_TARGET = atmega328
# 512 byte boot, SPIEN
fabduino8_isp: HFUSE ?= DE
# low power xtal (8MHz) 256CK/14CK+65ms
fabduino8_isp: LFUSE ?= E2
# 2.7V brownout
fabduino8_isp: EFUSE ?= 05
fabduino8_isp: isp
Then from a terminal (assuming you have the avr toolpath installed already) you can build the new bootloader with:
make fabduino8
You should now have a optiboot_fabduino8_atmega328.hex file in your optiboot folder. Now that we have the bootloader that we want to use, we have to tell the arduino software how to use it. Figure out where the boards.txt file is on your OS and add a board profile for the 8MHz board on a 328.
fab8.name=fabduino8
fab8.upload.tool=avrdude
fab8.upload.protocol=arduino
fab8.upload.maximum_size=32256
fab8.upload.maximum_data_size=2048
fab8.upload.speed=38400
fab8.bootloader.tool=avrdude
fab8.bootloader.low_fuses=0xE2
fab8.bootloader.high_fuses=0xDE
fab8.bootloader.extended_fuses=0x05
fab8.bootloader.unlock_bits=0x3F
fab8.bootloader.lock_bits=0x0F
fab8.bootloader.file=optiboot/optiboot_fabduino8_atmega328.hex
fab8.build.mcu=atmega328
fab8.build.f_cpu=8000000L
fab8.build.core=arduino
fab8.build.variant=standard
#################################################
fab8p.name=fabduino8p
fab8p.upload.tool=avrdude
fab8p.upload.protocol=arduino
fab8p.upload.maximum_size=32256
fab8p.upload.maximum_data_size=2048
fab8p.upload.speed=38400
fab8p.bootloader.tool=avrdude
fab8p.bootloader.low_fuses=0xE2
fab8p.bootloader.high_fuses=0xDE
fab8p.bootloader.extended_fuses=0x05
fab8p.bootloader.unlock_bits=0x3F
fab8p.bootloader.lock_bits=0x0F
fab8p.bootloader.file=optiboot/optiboot_fabduino8_atmega328.hex
fab8p.build.mcu=atmega328p
fab8p.build.f_cpu=8000000L
fab8p.build.core=arduino
fab8p.build.variant=standard
The same strangeness with the bootloader exists, while buring the bootloader the chip is properly detected as a atmega328, but when trying to use the arduino software to upload a sketch over ftdi the device signature is that of a atmega328p. Install and burn the boards the same ways.
For the lazy:
optiboot_fabduino8_atmega328.hex
optiboot_fabduino20_atmega328.hex