2014年7月16日星期三

Flash Programer Based on STM32F103

前些日子需要写flash芯片,图便宜淘宝了个CH341A。可是拿回来以后才发现,这货只能在Windows下用,相当不方便。试着在Linux里用QEmu跑WindowsPE,因为写很慢所以丢在那里吃东西去了,回来发现CH341A和flash芯片都很烫,上机没反应,flash芯片烧掉了。

想要搞一个Linux下也能用的,股沟里扒拉半天,找到了dword这篇《Linux 下离线烧写 SPI 闪存》

电路层面的东西,我基本是十窍通了九窍的程度,不过电路图看着还算简单,于是各种长草啊。可dword特别强调,不能买USB只能供电或做ISP的板子,而淘宝上STM32F103虽多,但在USB这个问题上的表述大多是“预留通讯功能”。

各种翻资料还是没把握,干脆就给dword写了一封信求教,没想到居然收到了回信。好吧,这下子不造都有些过意不去了…

卖家链接我就不贴了,设计做工并不漂亮,要资料什么都没有,而且焊上去的排针居然还有歪的。对着datasheep数,这板子上PXX管脚37根,VBAT管脚1根。剩下的是BOOT0和NRST,以及三组VDD/VSS和一组VDDA/VSSA。嗯,至少管脚是全部引出来了的。

由于买的是成品开发板,所以电路图上的大部分内容都不需要自己做。flash芯片上3、7两脚接的电阻,dword说是因为需要拉高的关系,阻值1至20k随意。而两个发光二极管串的R3是一个限流电阻,查了一下发现这个电阻的阻值是需要算的:

R = ( E - UF ) / IF

R为阻值,E为电源电压,UF为二极管正向压降,IF为二极管工作电流。不同厂家不同颜色的二极管参数都不一样,似乎很麻烦的样子。不过dword标了220R,所以电路中三个电阻我都用了200R的,貌似没什么问题。

另外这篇文章还提到说,建议在不使用外部电池时,VBAT和VDD间连一个100nF的瓷片电容。嘛,我这里没有,希望不会出岔子。

其实对我来说吧,最困难的是怎么把坏掉的芯片从转接板上弄下来,然后再换一块新的上去。

拆芯片的部分,网上的说法各种高大上,我这里东西又没那么齐全。最后还是先弄了一坨焊锡到管脚处一并加热才弄了下来,并且还是弄断了一根管脚。好容易搞定一半,又发现转接板上的焊盘伤了一点点。本以为除了人生中第一次拆芯片第一次焊芯片之外,还要贡献出第一次飞线,还好最后发现用不着。

软件方面,Ubuntu 14.04仓库里的flashrom是0.9.6.1,spispeed参数是0.9.7才加入的,所以需要自己编译一份:

sudo apt-get install gcc-arm-none-eabi libpci-dev libusb-dev libftdi-dev

cd ~/tmp
mkdir -p dep/include dep/lib

svn co svn://flashrom.org/flashrom/trunk flashrom
cd flashrom
make
sudo cp flashrom ~/opt/bin/

然后编译serprog-stm32vcp以及相关依赖:

cd ..
git clone https://github.com/esden/libcmsis.git
cd libcmsis
make
install_dir=~/tmp/dep make install

cd ../
git clone https://github.com/esden/libstm32.git
cd libstm32
C_INCLUDE_PATH=~/tmp/dep/include make
install_dir=~/tmp/dep make install

cd ../
git clone https://github.com/esden/libstm32usb.git
cd libstm32usb
C_INCLUDE_PATH=~/tmp/dep/include make
install_dir=~/tmp/dep make install

cd ../
git clone https://github.com/dword1511/serprog-stm32vcp.git
cd serprog-stm32vcp
# 交叉编译时LIBRARY_PATH不起作用,所以需要改common.mk,加上-L
C_INCLUDE_PATH=~/tmp/dep/include make

接下来编译stm32flash,一个用于将固件写入开发板的工具:

cd ../
git clone https://git.gitorious.org/stm32flash/stm32flash.git
cd stm32flash
make

一切就绪。现在将开发板的BOOT0拉高(ISP模式),接上TTL线并插入PC,给开发板上电,然后用stm32flash将固件写入开发板:

sudo ./stm32flash/stm32flash -b 115200 -w ../serprog-stm32vcp/serprog_vcp.bin -v /dev/ttyUSB0

写完以后TTL线就可以拔掉了。将BOOT0拉低并插入USB线,dmesg会有以下输出:

[ 2707.384103] usb 1-1.4: new full-speed USB device number 8 using ehci-pci
[ 2707.478418] usb 1-1.4: New USB device found, idVendor=0483, idProduct=5740
[ 2707.478423] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2707.478426] usb 1-1.4: Product: flashrom.org serprog-STM32VCP
[ 2707.478429] usb 1-1.4: Manufacturer: STMicroelectronics
[ 2707.478431] usb 1-1.4: SerialNumber: 84FF05086333
[ 2707.519125] cdc_acm 1-1.4:1.0: This device cannot do calls on its own. It is not a modem.
[ 2707.519155] cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device
[ 2707.519585] usbcore: registered new interface driver cdc_acm
[ 2707.519589] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

然后应该就可以用了:

sudo flashrom -p serprog:dev=/dev/ttyACM0:4000000,spispeed=36000000 -r flash_orig.bin
sudo flashrom -p serprog:dev=/dev/ttyACM0:4000000,spispeed=36000000 -v flash_orig.bin
sudo flashrom -p serprog:dev=/dev/ttyACM0:4000000,spispeed=36000000 -w somefile.bin

实际效果方面,我这边用一块MX25L12845测试下来,spispeed参数只能设置为18000000才可以稳定运行。一次读取耗时约21s左右,平均780KiB/s。这个速度倒是跟dword给出的数据差不多,不过写入方面却没想象的快。

flashrom为了减少flash芯片的损耗,在写入时会先读取一次以确定要更新的块,写完了会再校验一次,所以一次完整的写入要读两次写一次。我测试了几次,整个过程耗时大概在5到6分钟的样子。以6分钟计算,扣除两次读取,写入的速度大概是51.5KiB/s。

根据dword的说法,spispeed是根据flash芯片的工作频率来的。至于我这里的测试结果虽然不理想,但也“不算太离谱”,或许跟SPI连接线和USB电缆有关。嘛,暂时不管了,能用就行。

另外就是,flashrom目前在Windows下也是可用的,只是需要自己编译。有需要的话,可以用我这里编译好的版本,Ubuntu 14.04 x64和Windows版的flashrom都有。

如果要在Windows里用,除了libusb-win32-bin-1.2.4.0.zip外,还需要STM32的VCP驱动