|
Using an Arduino as a programmerBackgroundThe Arduino bootloader is a small program that runs on a microcontroller, typically Atmel, enabling programs to be uploaded to the microcontroller via the serial port. Microcontrollers are normally supplied blank, so initially the bootloader must be programmed in using a programmer. Also sometimes the bootloader needs to be updated or replaced. A program called ArduinoISP located in "Examples" allows an Arduino to be used as an AVR programmer. It doesn't matter which Arduino variant is used, but in my case it is an Uno. I've been finding details of the programming connection here and there, so here's my version: The AVR programming interface uses 4 pins, the Reset pin to enter programming mode then the three SPI pins SCK, MOSI and MISO. The Reset pin can be disabled, in which case a voltage pulse is needed to force the device into programming mode. The ArduinoISP program can't send the voltage pulse so it can't reprogram a device unless the Reset pin is enabled. The ArduinoISP program normally uses SCK, MOSI, MISO and an additional pin for the Reset signal.
It is not clear what purpose the larger connector serves beyond creating a requirement for yet more adaptor cables. Presumably some pins may be reserved for future functions. There is a diagram showing how to "jump start" one Arduino Uno from another in the ArduinoISP page: https://docs.arduino.cc/built-in-examples/arduino-isp/ArduinoISP/ The Programmer and target pins 11 (MOSI),12 (MISO), 13 (SCK), 5V and Ground are interconnected The Programmer pin 10 connects to the target Reset pin. Alternatively the 6 pin programming connector could be used. There is also an instruction to place a 10uF capacitor between the programmer Arduino's Reset pin and ground, this is to prevent that board from inadvertently resetting and running its own bootloader instead of ArduinoISP. So far I have not found this to be necessary.Special considerations are necessary when one or both devices are 3.3V, these are described in detail. Modification for convenienceIf the programmer Arduino was modified to have a two way switch such that the programming connector pin 5 could be routed to either Reset or pin 10 then the programming connector could be used as an output such that a simple 6 way IDC cable could be used to link the programmer Arduino to the target Arduino. AVRDUDE and AVRDUDESSAVRDUDE is the command line programming tool used by the Arduino IDE to actually upload programs. It is also used by PlatformIO and frequently referenced in documentation. Due to the number of options command lines can get quite bloated. AVRDUDESS is an AVR programmer with a GUI, it opens as a dialog window with boxes for the required parameters, and greatly simplifies the programming process when you have a finished "HEX" file to program rather than a sketch or project. I highly recommend it if you need to work with the microcontroller directly. Some notes about bootloadersWhile it might seem as if the term "booting" a computer refers to kicking it awake the actual origin is the phrase "to pull your self up by your bootstraps". Historically a computer might power on in a completely blank state and an operator would have to manually load a short "bootstrap" program that would enable the computer to read the actual program from an input device. The loading process might involve toggling switches to set each byte in turn. This meant having a control panel that gave the operator direct access to the computer's memory. By hardwiring the start up code into Read Only Memory the control panel was no longer needed as the machine could start itself, so the expense of adding the ROM was offset by the removal of a considerable number of lights and switches, thus the blinking lights of the 1960s gave way to the blank panels of the 1970s. When required control panel functionality could be very effectively emulated by software. In embedded computing a program is typically self-contained, containing everything needed to start the microcontroller from initial power-on, but adding a boot loader enables the program to be replaced easily without needing a specialized device programmer. There are different strategies for doing this, on some systems the bootloader is at the bottom of memory shifting the user program up, this may mean the user program needs building specifically with the higher start address to support the boot loader Other systems put the bootloader at the top of memory, meaning the main program start address stays the same but a means is needed to divert the reset to the bootloader as required. This appears to be how it is done on Arduino, meaning code does not need to be built a specific way, the same program can be loaded onto an Arduino or programmed directly. Replacing a bootloaderAlthough it would seem a bad idea to allow a bootloader to overwrite itself some systems may allow this, potentially putting a device in an unrecoverable state. If a bootloader is required to replace itself then a special strategy is required to prevent entering an unrecoverable state. A simple strategy might be to copy the bootloader to RAM and jump to the RAM copy, allowing the original bootloader to be overwritten, but this is risky as if programming fails the system could be left unrecoverable. A better solution might be to write the new version to RAM, verify the copy, then copy the new loader over the original. This is still vulnerable to being interrupted, though writing from RAM to flash is typically very fast, sometimes less than a second, so the window for failure is small. To avoid the small risk of the process being interrupted we might write a copy of the loader to unused ROM space, jump to it, then point the reset vector at the copy. Then the original bootloader may be safely overwritten and only when the new bootloader is confirmed functional the reset vector can be pointed to it. This way if the update process is interrupted there is still one working bootloader to perform recovery with. This does require a changeable reset vector though, and typically microcontrollers just start up at location zero. HistoryIntel MCS® BASIC-52 implemented a BASIC language factory programmed on an 8051 type microcontroller, but significantly it allowed the microcontroller to program EPROMs. This was achieved by code running on the 8051's internal ROM switching its address and data bus pins into being programmed I/O pins and writing a programming sequence to the pins. This meant a development board could be put together with blank EPROM devices and a program transferred to EPROM later. The instruction manual I saw dated from 1986, so it is the first instance I'm aware of where an embedded system could program itself with code transferred over a serial port. A voltage generator was required to program the EPROMs and they would still need erasing so it wasn't a self contained solution. As far as I'm aware self-erasing EEPROM devices were a few years away from general use. NXP LPC microcontrollers have a loader mask-programmed into the microcontroller, meaning that from their factory-new condition they may be programmed using only a serial connection. Grounding one pin at power on puts the device in programming mode. At least one device in the series can be programmed via USB as if activated the loader presents itself as a minimal mass storage device that only accepts program code. The "Classic" Arduino consists of a USB to serial converter and an AVR microcontroller that is pre-programmed with a serial bootloader. Oddly enough the current implementation uses a microcontroller for its USB-Serial converter so it would be technically feasible to put programmer code on the converter and implement direct programming, but this is not done. Some other development platforms do implement direct programming. Microchip's MPLAB xpress, MBED and Cypress PSoC development boards all feature two microcontrollers, one serves as USB interface and programmer and the other is the target device. Since the USB microcontroller implements direct programming the full memory space of the target is available. |