Donnerstag, 31. Dezember 2015

SPI Flash programmer with Arduino Pro Mini

Last updated 01.01.2016
I recently ordered a small Wifi bridge/repeater dongle which I wanted to use to offload the WPA2/AES encryption from my satellite receiver and have it connected virtually by ethernet. This Vonets Mini300 can't cope with long WPA passwords though with special characters - a "+" sign gets stored as space, thus it won't connect to my WLAN. The firmware was quite outdated and the update servers have changed, so the internal update mechanism doesn't work. The black and red wires are for a serial console to access the operating system on the little box directly and to see if it is possible to fix via command line interface. Unfortunately, the system spits out the boot messages, but is locked against keystrokes.

I started to investigate alternatives: OpenWRT for the MT7620N processor should work. Or the manufacturer sends me the most recent firmware so I can flash it myself. But there we are: Like usual PCs BIOSes, Wifi routers use SPI flash rom for storing the firmware and data. You can buy special flashers and use the software the manufacturer offers for it. Or - you build your own!

It's actually quite easy. You can use an ATmega board, connect it with USB-to-serial-converter to your computer, and wire up the Flash IC directly to the ATmega SPI pins. My first attempts used exactly this setup, but with plenty of DuPont cables and thus possible spots for errors - and for noise on the lines which can (and did!) disturb proper operation.

For such a flash writer you need:
- An Arduino Pro Mini board (cheap and runs with 3.3V)
- A USB-to-serial converter like FT232RL, PL2303, CP2102, ... (I used a PL2303) with 3.3V output
- Very useful is a SOIC8/SOP8 clip for easy access to the Flash ROM IC.

Wire the USB-to-serial-converter to the Arduino Pro Mini. If you want auto-reset for easier flashing, you need to solder a wire from Pin 2 of the PL2303 to Reset or DTR on the Arduino - but through a 100nF ceramic capacitor. Look at the photo at the end to see my version of the hack.

- flashrom -
- frser-duino for the ATmega328 -

The frser-duino Makefile contains some entries which you should adopt. I found out the hard way that the bootloader of the Arduino only talks at 57600bps. You need to tell that to avrdude via -b option, and set this in the Makefile for frser-duino. Also you can set a second bitrate below that line. I set it to 230400 and it works great; contrary to the 115200bps which the unmodified version offers. You should set the proper interface for your USB-to-serial-converter, the default /dev/ttyS0 is for Linux systems; on my MacBook Air, it is /dev/tty.usbserial.

Then you start building and flashing the firmware with:

make clean all program
 This will build the firmware and upload it by issuing the correct avrdude command line:
avrdude -c arduino -p m328p -P /dev/tty.usbserial -b 57600  -U flash:w:frser-duino.hex
That's it! Wire up the SPI Flash ROM to the proper SPI Pins on the Arduino or solder a board with a DIP8 connector which is correctly connected and you're good to go.

This way I can just plug the programmer into the computer and directly use it with flashrom to read or write SPI flash roms.

Now with the optimized firmware with 230400bps support the reading and writing significantly improved in terms of speed.
koepi$ time flashrom --programmer serprog:dev=/dev/tty.usbserial:460800 -r 16MB_empty.bin  
flashrom v0.9.8-unknown on Darwin 15.2.0 (x86_64) 
flashrom is free software, get the source code at
Calibrating delay loop... OK. 
Warning: given baudrate 460800 rounded down to 230400. 
serprog: Programmer name is "frser-duino" 
serprog: requested mapping AT45CS1282 is incompatible: 0x1080000 bytes at 0x00000000fef80000. 
Found Winbond flash chip "W25Q128.V" (16384 kB, SPI) on serprog. 
Reading flash... done. 
real 12m42.328s; user 0m6.428s; sys 0m12.367s

I also tried the STM32F1xx based vserprog, but the USB connection wasn't returning the expected results. Flashrom couldn't initialize the programmer. The authors of the code state that minimal changes are necessary for setting the necessary pull-ups, but I didn't find the spots in the code where to add that - bummer! With 36MHz SPI frequency, direct USB support without extra dongle and, most important, DMA it is the best you can get performance-wise.

With this SPI flash programmer I can flash the newest firmware from the manufacturer - the bug is still there though. But it can access it's update server so there is still hope for a fix in the near future.

I also cut-and-copied the firmware image - the U-Boot Bootloader didn't allow any access to it's shell, so I use breed from HackPascal now. The first 192kByte are Bootloader (pad with zero bytes up to the 192kByte boundary), then there's config data in the next 128kByte (cut out from the original flash dump). After that at 327680 bytes the firmware itself is stored. MT7620N firmwares from OpenWRT don't work, unfortunately. I tried even to build a version myself, but with the same result. Using a bigger SPI flash rom works, but there is no use for it when only the original firmware for 4 MByte flash is running on the machine.

Update 01.01.2016: I had to reduce the speed to 115200kbps again for reliable operation. The programmer stopped mid-reading after some time with 230400kbps.
Erase/write done.Verifying flash... VERIFIED.serprog: Output drivers disabled
real 61m53.970suser 0m10.722s
sys 0m50.472s