2018年4月8日日曜日

STM32CubeMX で出力される code の start addressを 0x4000 に変更する方法

ArmBootloader でその後起動する firmware の start address は MCU の reset vector に配置するのではなく、ArmBootloader で管理する firmware 領域の top に配置する必要がある.
今回 STM32F767 (実際は STM32H743 を使用したいが, NUCLEO 未到着) と STM32CubeMX が生成する code で, 単に board 上の LED を点滅される (GPIO を high / low させるだけ) code で FreeRTOS を追加すると FreeRTOS 部分で処理が止ってしまう現象があり 0x40000 に移動させるのに苦労してしまったので, 記録しておく.

環境
arm-none-eabi-gcc:   (15:5.4.1+svn241155-1) 5.4.1 20160919
STM32CubeMX:  4.25.0 (STM32F7: 1.11.0)

ちなみに STM32F767 の Flash ROM の Sector の都合により firmware の top address を 0x4000 でなく, 0x40000 となっています (ゼロの数に注意).


最終的な変更部は以下の通り,
### 1.   $(project_top)/STM32F767ZITx_FLASH.ld  内 FLASH 領域の変更
FLASH (rx)      : ORIGIN = 0x8040000, LENGTH = 0x1c000      /* address, size に変更 */

### 2.   $(project_top)/Src/system_stm32f7xx.c の VTOR の変更
  extern uint32_t       g_pfnVectors;      /* defined in startup_stm32f767xx.s */
  SCB->VTOR = &g_pfnVectors;


以上であるが, うまくいかなっかった点は, 2 番目の g_pfnVectors の扱いで, .s 内の assembler の label を C から参照するのに, label = pointer = address の場所という感覚であるので
     extern uint32_t       *g_pfnVectors;
     SCB->VTOR = g_pfnVectors;
したが, これでは ng で, assembler の label は, C はなんらかの value その物という解釈らしいので, uint32_t * でなく, uint32_t と extern し, VTOR の vector top register に格納する時に & するのが良いみたいだ.




STMCubeMX が出力する Makefile の SOURCES にいくつかの source が 2 重に定義されており linker で error になる. 手で削除が必要.
また, それなりに動作する sample code が得られると思ったが, 単に compile が成功する code が得られるだけで, たとえば usb audio でとりあえず stream が STM に流れるものが入手できるわけではなく, 色々 code の追加が必要そう. Kinetis はそれなりに動く code が入手できるのだが, ST はあまりそう気はないのだろうか.   RCC の HSE の周波数設定が間違っていただけでした...