+41 22 566 01 87
+41 22 566 01 87
A USB AVR programmer made from discrete components.
|Status du project|
|Date de début||13/11/2014|
|Status||work in progress|
Ok, so, you may argue that there are already (too) many ways to program AVRs. If you have a serial or parallel port, many very simple solutions exit. But as soon as you are stuck with USB, you needs some extra logic, typically either some kind of USB to GPIO chip/cable or another uC. If you don't like the former (many need closed-source drivers), you can use an AVR-based programmer. Yes, Arduinos can be used to program arduinos.
Hey, but that's a chicken-egg problem: how to program the first programmer? - This project aims at providing a solution.
The programmer is built using (optional in parenthesis):
To test the stuff:
|[usbbasis] Interested in joining this project|
|Nom||participation active||participation passive||suivre de loins|
Reading the USB specs, I came across the port test modes. They would make perfect GPIOs for computers with only USB ports. Unfortunately, these modes only work in high-speed mode, where signal levels are somewhat small (reaching only 800mV without termination). I would need to build a small level shifter. A USB device made from discrete electronics, that just has to be done!
D- cannot be driven independently, but only three combinations are possible
SE0_NAK, where either one line is high or none, respectively (i.e. never both lines are high). Now, the AVR samples the data line on the rising edge of the clock. To send a one, the normal operation would be:
For a zero:
… which would ask for all four combinations.
Well, luckily this situation can also be achieved with the available three states by delaying the data line.
Unfortunately, the story is not yet over… after bread-bording a bit with a simple npn-inverter circuit, the following issue caught me: the arduino is power hungry on
SCK (arduino pin 13), where it has an LED connected. The level shifter needs a bit more driving strength…
Three issues need to be fixed:
MOSI) signal needs to be delayed wrt the clock (
That's an X-mas hack! – finally a quite minute to connect up everything (the ISP pins are also available on the I/O pin headers of the arduino, a perfect place to hook up a logic analyser):
Let's send the init programming sequence
AC-53-00-00 (MSB first) and see if the AVR answers with
… it DOES! Merry Christmas! (and more to come next year)
avrdude hacking! – reading does of course not work, but here just an example command:
$ ./avrdude -C avrdude.conf -p m328p -c usbbasis -P 250.3.3 [...] avrdude: Device signature = 0xff003f avrdude: Expected signature for ATmega328P is 1E 95 0F [...] avrdude done. Thank you.
This is some micro bootloader that may be used to install a real bootloader. I do not know if it is really working, but keep it here for reference. 26 bytes and no warranties!
; ub -- the micro bootloader V0.01a ; Copyright (C) 2015 Magnus (magnustron) ; ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; ; You should have received a copy of the GNU General Public License ; along with this program. If not, see <http://www.gnu.org/licenses/>. ; This is a "boot loader loader" used to install a bootloader via serial port. ; It is quite minimal. ; Supported devices (tested): ATmega328 ; Baud rate: fosc/16 (if not set to something else but default by bootloader...) ;loop: clr r29 ldi r28,0xB8 ;enable RX, TX and add a few ones std Y+9,r28 ;UCSR0B (0x00C1) wait_data: ldd r16,Y+8 ;UCSR0A (0x00C0) sbrs r16,7 ;check RXC0 rjmp wait_data ldd r17,Y+14 ;UDR0 (0x00C6) wait_addr: ldd r16,Y+8 ;UCSR0A (0x00C0) sbrs r16,7 ;check RXC0 rjmp wait_addr ldd r28,Y+14 ;UDR0 (0x00C6) st Y,r17 spm ; rjmp loop ; Looping is done via wrapping of IP. Well, as long as nothing else (like a bootloader) is written to the flash...
With an ardiuno uno this python snipplet was used as a proof of principle for the communication “protocol”:
import serial import time PORT='/dev/tty.usbmodemfd121' # the arduino on my Mac BAUDRATE=115200 # this is since I still have the arduino bootloader, which leaves its traces ser=serial.Serial(port=PORT,baudrate=BAUDRATE) time.sleep(3) print ser.write(''.join(map(chr,['E',0xC6]))) ret=ord(ser.read(1)) print '%02X: %c' % (ret,chr(ret))