OpenOCDで、STM32のフラッシュ書き込みを行いたい。
いままで YAGARTOで配布されていたものを使用していたが、GPLのOpenOCDを、プロプライエタリなFTDI社のFTD2XXライブラリを使うバイナリで配布するのはまずいということで?YAGARTOのOpenOCDバイナリ配布はなくなってしまった。
http://www.freddiechopin.info/では、フリーのlibftdiを使う版が配布されているが、libftdiはFTDI2XXより遅いらしいし、Windows用ドライバもFTDIのから換えなければならないし、ここで配布されているものは、JTAGKeyっていう奴用みたいで、私の使ってる Olimex ARM-USB-OCD では動かないみたい。
本家OpenOCDをソースビルドすればFTD2XXが使えるのでそうしたい。でもWindows上だから面倒だな…と思ったら 非常に丁寧にOpenOCDのソースビルド方法を解説してくださっているかたがいらっしゃったのを見つけたのでやってみた(ありがとうございます!)。
ただ、このとおりビルドしようとしたら、いざmakeの段階で「このソースは古いよ。もうsvn使うの止めたから最新ソースはGITでとってね」ということになっていた。
GIT使ったことないので現時点での最新リリース候補 OpenOCD-0.3.0-rc0.tar.bz2 をもらってきてビルドした。
さて、これで、YAGARTO配布の openocd-r520-20080322 よりも安定して動く(と個人的には思える)OpenOCDが使える状態になった。
しかし、現在のOpenOCDは、コマンドがだいぶ変わっていて、openocd-r520-20080322 のころに使っていた .cfgが、そのままでは動かない。
gdbやtelnet経由(それと、IDE(Eclipse))で使う分にはいいのだろうけど、私は、makeやバッチファイルから起動してSTM32のFLASHに書き込みを行いたい。
JTAGチェイン定義関係はスクリプトが用意されているので簡単だったが、スクリプトでのFlash書き込みはどうすればいいのか、かなり試行錯誤した。
以前は
flash.cfg
# script configuration # target_script target_script 0 reset flash.script
openocd -f flash.cfg と実行すれば、ターゲットリセット後に スクリプトファイル flash.script を実行してくれたのだが、target_script コマンドが無くなってしまったので、どうすればいいのかわからなかったのだ。
それと、いままで、単純に .cfg ファイル内に書いておいても実行されていたコマンドが、現在のOpenOCDでは、エラーになる(でも、telnetから投入すると通る)。
試行錯誤した結果、現在 OpenOCD 0.3.0rc0では、以下のようにしてSTM32のFLASHにコマンド一発で書き込みができています。
flash.cfg
# OpenOCD STM32 Flash write cfg telnet_port 4444 gdb_port 3333 source [find interface/olimex-arm-usb-ocd.cfg] source [find target/stm32.cfg] stm32.cpu configure -event halted { wait_halt sleep 10 poll sleep 10 stm32x mass_erase 0 sleep 10 flash write_image flash.elf sleep 10 } init reset halt reset run exit
openocd -f flash.cfg で FLASH全消去後、ELFイメージ flash.elf を書き込み、STM32再起動。
1. stm32.cpu configure -event で、ターゲット stm32.cpu に対するイベント発生時のスクリプトを定義する。
ここでは、haltさせた時のイベントを定義した(関数定義のようにしてもいいがここではイベント定義ブロック内にコマンドを列記した)。
2. init で初期化
3. reset halt で ターゲットリセット & HALT (で、ここでhaltedイベントが発生して、上記イベント処理が実行されてFLASH書き込みする)
4. reset run でターゲットリセット & RUN
5. おわり(OpenOCD終了)
どうも、wait_halt 等は、イベント内でないとエラーになるみたい?
現在困っているのは、STM32にすでに書き込んであるプログラムが、リセット直後にDEEP SLEEP(STOP)に入れるようになっていると、reset halt がちゃんとできないということ。どうしたらいいのかなあ。。。
その後、ねむいさんのブログを拝見したら、イベント駆動にしなくても、proc定義すれば、コマンドラインからそのprocを実行できることを教わった。このほうが、コマンドラインから、動作ならびにファイル名を指定できるし、1個のcfgファイルでflashにもデバッグにも使えるので便利ですね。
openocd.cfg
# OpenOCD STM32 cfg with Flash proc telnet_port 4444 gdb_port 3333 source [find interface/olimex-arm-usb-ocd.cfg] # SRAM 20KB version chip set WORKAREASIZE 0x5000 source [find target/stm32.cfg] proc flash_program {ELF_FILENAME} { init reset halt stm32x mass_erase 0 flash write_image $ELF_FILENAME verify_image $ELF_FILENAME echo "flash program complete. reset and run" reset run exit } init
openocd -f openocd.cfg -c “flash_program flash.elf”
で、Flashイレース・書き込み実行(と、ベリファイ)
フラッシュ書き込み時に
Warn : not enough working area available(requested 16384, free 16336)
と出るので、現在使ってるのはSRAM 20KBのチップなのでワークエリアサイズ指定をするようにしたらそのメッセージは出なくなった…が、SRAM 10KBのチップのときはどうすりゃいいんだろうか?
コメント
今までOPENOCD-0.1.0を使ってstm32f103をプログラムしていましたがstm32f105を使い始めたところ旧バージョンのOpenOCDは対応してなくてOpenOCDをバージョンアップすることになりました。
OpenOCD-0.3.1の構築までは簡単に出来たものの以前のコマンドが使えなくてさんざん探し回った果てにこのブログを見つけて無事使えるようになりました。
貴重な情報、ありがとうございました。