2017年10月14日土曜日

メモ:STM32F4のメモリ配置

 STBee F4miniに使われてるSTM32F405RGTには、メモリが192kB搭載されている。
 0x10000000からの64kB、0x20000000から112kB、0x2001C000からの16kBの3種類。
 112kと16kは連続していて、128kBとして使える。この2箇所は同時にアクセスすることができるので、例えば112kをメインのメモリとして使い、16kはUSBやEthernetのバッファとして使う、というような用途らしい。
 64kはARMコアとは接続されているが、DMAバスとは接続されていないので、64k領域にある配列をDMA転送しようとするとハングアップするらしい。

 今までは128kをメインのメモリとして使い、64kをスタックとして使っていた。これはねむいさんのリンカそのもの。しかし、FreeRTOSを使っているので、スタックはほぼ全く使っていない。
 今回、試しにFreeRTOSのスタックを64k領域に配置し、128kをそれ以外に使うようにしてみた。FreeRTOSは今のところ16kほど使ってるので、まだ48kほど開いてる。DMA転送で使う場合はstaticで宣言して128k領域から確保すればいい。またmallocも128k領域から取ってくるようになる。

 配列のアドレスを指定するのは、リンカスクリプトとかでうまくできるのだろうが、方法がわからなかったので、 static uint8_t *ucHeap = (uint8_t *)0x10000000; のように、直接指定することにした。これはFreeRTOS/portable/MemMang/heap_4.cの100行目あたりに書いてある。配列の宣言をポインタに置き換えたもの。リンカスクリプトには64k領域を書いていないので、コンパイラがこの領域を使うことはできない。configTOTAL_HEAP_SIZEは64KiBにしておけばok。


 ということで、微妙に使い勝手の悪い64k領域をそれなりに活用しつつ、128k領域を目一杯使えるようになった。
 mallocで確保できる領域も増えたので、動的にメモリを使う機能も使いやすくなった。


 Luaを走らせたいんだけど、ちょっと苦戦中。

追記
 もうちょっとスッキリした方法(たぶん)。
 FreeRTOSConfig.hに #define configAPPLICATION_ALLOCATED_HEAP 1 を追加する。
 freertos_heap.cという、FreeRTOS.hをインクルードし、uint8_t ucHeap[configTOTAL_HEAP_SIZE]; と配列だけを宣言したソースを作る。
 リンカスクリプトのセクションに
.freertos_heap_sec :
{
*freertos_heap.o(.bss .bss.*)
} >RAM3
 を追加する。
 これで、FreeRTOSのヒープ領域をRAM3に確保できる。

 main.cの最初のほうでスタックのアドレスを変数に保存して、後で表示してみると、0x1000000の領域に確保されている。FreeRTOSのスレッド内でスタックのアドレスを見ても、0x10000000の領域に確保されている。
 ということで、64kの領域にFreeRTOSのヒープを確保しつつ、残りの領域はOS外のスタックを確保し、残りの128kをmallocに使う、という感じになった。今のところ、FreeRTOSでは16kくらいしか使ってないらしいが、とりあえず32kを確保している。

 今までのheap_n.cを書き換える方法だと、Cubeで出力するたびに戻されるので、面倒だと思う(未確認)。今回の方法だと、一応Cubeの制御外のはず(未確認)。

0 件のコメント:

コメントを投稿