STM32F0-Discovery + OpenOCD
講義で使おうとSTM32F0-Discoveryを購入したら、主催者側がまとめて買ったとかで出番がなくなった。
でに、いつものように、ねむいさんの置場からOpenOCDの最新版をDL。(ねむいさんありがとうございます)説明を見ると。
-OpenOCD |
CMSIS-DAPをサポートしたんだと思ったら、0.8.0で既にサポートされていた。
テストプログラムは、同じく置場のkick startをDLした。
このテストプログラムは Lチカ+シリアル でFlashに書かないでRAMで動かす。
OpenOCDを起動して
openocd.exe -s ./tcl -s ./image -f board/stm32f0discovery.cfg |
telnetでlocalhost:4444に接続。RAMにロードして動かすコマンドは
> reset halt |
set sp 0x20002000, set pc 0x20000E25は間違い
reg sp 0x20002000, reg pc 0x20000E25が正しい
(2015/11/29)
<<stm32f0_ram_exec.tcl>>
proc load_elf { loadfile } { # vector table address set vbr 0x40010000 # (top of SRAM) set mode 3 # reset and halt reset halt # set vector table address mww $vbr $mode # load ELF file onto SRAM(0x20000000-) load_image $loadfile return } proc run_sram { } { # vector address (top of SRAM) set vectaddr 0x20000000 # get initial SP and reset handler mem2array vect 32 $vectaddr 2 # display top of vector 4 elements mdw $vectaddr 4 # set initial SP into SP reg sp $vect(0) # set reset handler int PC reg pc $vect(1) # execute now resume return } proc load_run { loadfile } { load_elf $loadfile run_sram return } |
こんなスクリプトを作っておいて
openocd.exe -s ./tcl -s ./image -f board/stm32f0discovery.cfg |
で CPUの停止 → バイナリ―のロード → レジスタ(SP,SP)の設定 → 実行 してくれる。
←リンク先にAVI(792.5k)
置場を見ていると、STM32VL-Discoveryのサンプル(TFT/OLED Module Control Sample with ChaN's FatFs(STM32VL-MMC Driver))があったので、STM32F0DiscoveryのテストプログラムをSTM32VLDiscovery用に作ってみた。
main.cはインクルードするヘッダファイルを除いてほぼ同じだ。以前作ったテストプログラムは、機能を削ってようやく8KのRAMの収まるくらいだったが、コンパイルすると、4.5kに収まった。
ところが、RAMにロードして動かそうとするとうまく動かない。LEDは点灯するだけで点滅せずシリアルにメッセージも送信されない。
ソースを見ても分からないのでデバッガで追ってみた。こんなことならInsightを入れとけばよかったと思ったが、gdbでシコシコ
実行する度に暴走する場所が異なる。メインから全てステップで追ってみるとxprintf()の中でgdbが返事をしなくなる。ところがxprintf()にブレークポイントを張って実行すると、ブレークポイントにたどり着く前にどこかへ行ってしまう。挙動不審だ。
LチカでSysTickを使っているのだが int TimingDelayの値がデクリメントされていないことに気がつた。そこで、SysTick_Handlerにブレークポイントを張ってちゃんと割り込みが掛かっているか確認すると、SysTic_Handlerに飛んでこない。
割り込みべタはRAMに設定しているのに??
悩むこと半日とうとう見付けた
src/hw_config.c
/************************************************************************** |
NVIC_SetVectorTable()は
lib/STM32F10x_SetPeriph_Driver/src/misc.c
/** |
この関数で VTOR(Vector Table Offset Register)を設定して割り込みベクタをリマップしている。
VECT_TAB_RAM/ VECT_TAB_FLASHはmakefieでコンパイル時に -DVECT_TAB_FLASHが宣言されている。
OpenOCDでバイナリをRAMにロードして、実行する前に割り込みベクタ・テーブルをRAMに設定しているのだが(mww 0xE000ED08 0x20000000) main()の先頭で呼ばれるSet_System()関数から Set_System() -> NVIC_Conviguration() -> NVIC_SetVectorTable() の順で呼ばれて割り込みベクタをFLASHの先頭に戻していたようだ。
コメントを見ると、/* 20090429Nemu */のシグネチャがある。
ねむいさんはプログラム中で割り込みベクタ・テーブルをリマップするというお考えだったらしい。それに気が付かないで自分で設定していたのが原因だった。
でもね、STM32F0DiscoveryのKickStartではベクタテーブルのリマップしてないんだよね。^^)尤も、cortex-M0にはVTORはないんだけどね。
cortex-M0にはVTROはなくても、ベクタテーブルのリマップ関数はあるのではと思い、探してみるとちゃんとあった。
/lib/STM32F0xx_StdPeriph_Driver/src/stm32f0xx_syscfg.c
/**
* @brief Configures the memory mapping at address 0x00000000.
* @param SYSCFG_MemoryRemap: selects the memory remapping.
* This parameter can be one of the following values:
* @arg SYSCFG_MemoryRemap_Flash: Main Flash memory mapped at 0x00000000
* @arg SYSCFG_MemoryRemap_SystemMemory: System Flash memory mapped at 0x00000000
* @arg SYSCFG_MemoryRemap_SRAM: Embedded SRAM mapped at 0x00000000
* @retval None
*/
void SYSCFG_MemoryRemapConfig(uint32_t SYSCFG_MemoryRemap)
{
uint32_t tmpctrl = 0;
/* Check the parameter */
assert_param(IS_SYSCFG_MEMORY_REMAP(SYSCFG_MemoryRemap));
/* Get CFGR1 register value */
tmpctrl = SYSCFG->CFGR1;
/* Clear MEM_MODE bits */
tmpctrl &= (uint32_t) (~SYSCFG_CFGR1_MEM_MODE);
/* Set the new MEM_MODE bits value */
tmpctrl |= (uint32_t) SYSCFG_MemoryRemap;
/* Set CFGR1 register with the new memory remap configuration */
SYSCFG->CFGR1 = tmpctrl;
}
|
MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM); をmainの頭で呼んでやればよさそうだ。
ついでに、スタートアップルーチン("lib/CMSIS/Device/ST/STM32F0xx/Source/Templates/gcc_ride7/startup_stm32f0xx.s)も調べてみると、Reset_Handlerの先頭でスタックの設定も行っていることが分かった。
つまり、OpenOCDのコマンドは
> reset halt |
で良さそうだ。
最近のコメント