stm32h743でDMAを使う

stm32h743搭載のボードを作ったらDMAが動作しなくて悩んだこと

※この記事はstm32CubeIDEを使うことを前提にして書いてあります

stm32h743はクロック480MHz、内蔵Flash 2MByte、内蔵SRAM 864KByte maxでキャッシュメモリ、FPUを備えていて
アナログインターフェースとして16bit A/D 、OPAMP、コンパレータを内蔵しTFT-LCDコントローラのLTDCも搭載した組み込み用高性能マイクロコントローラです。

超高性能&機能てんこ盛りなのは嬉しいかわりに内部バスアーキテクチャが複雑になっているためstm32CubeIDEまかせではDMAアクセスがうまくいかず、解決までに暫く悩みました。

結局は「リファレンスマニュアルをちゃんと読めよ。」ということに尽きるわけですが、stm32CubeMXのGUI画面でパラメータ設定をすれば初期化プログラムが簡単に出来てしまうという楽さに慣れてしまった身としては久しぶりにリファレンスマニュアルを睨みながら苦労していた昔のことを懐かしく思い出すことになりました。

stm32h7xシリーズでDMAが動かない理由

1.キャッシュメモリのせいでDMAがRAMに書いた値がプログラムのメモリアクセスには反映されない。(ADC等、DMA→RAMの場合)

 プログラムはキャッシュメモリを介してRAMをアクセスするため、プログラムが関知しないDMAによるRAMへの書き込みではRAMの状態をキャッシュメモリに反映する特別な命令が必要となります。

2.DMAによって使えるRAMのブロックが決まっている。

 下図のようにstm32h743ではUART用のDMA1,DMA2はD2ドメインのRAM、ADC用のBDMAはD3ドメインのRAMに接続されているため各DMA用のバッファはそれぞれ別のRAM領域に割り当てる必要があります。

stm32h743でDMAを使うための手順

1.キャッシュメモリの設定

詳細はねむいさんのブログを参照して下さい。
stm32CubeIDEで次のように設定します

(続き)

2.リンカスクリプトファイルの修正

stm32CubeIDEが自動的に作るリンカスクリプト *_FLASH.ldではITCMRAMを標準の変数、スタックエリアとして使っていてD1,D2,D3ドメインの割り当て用ラベルが無いため下記のようにRAM_D1、RAM_D2、RAM_D3セクションを追加します。
リンカスクリプトはstm32cubeMXでコードジェネレートしても変更されないので一度だけ追加しておけばOKです。

/* User_heap_stack section, used to check that there is enough RAM left */
 ._user_heap_stack :
 {
   . = ALIGN(8);
   PROVIDE ( end = . );
   PROVIDE ( _end = . );
   . = . + _Min_Heap_Size;
   . = . + _Min_Stack_Size;
   . = ALIGN(8);
 } >RAM

 .RAM_D1 :
 {
	. = ALIGN(32); 
 } >RAM_D1
 
 .RAM_D2 :
 {
 	. = ALIGN(32);
 } >RAM_D2
 
 .RAM_D3 :
 {
 	. = ALIGN(32);
 } >RAM_D3
 
 /* Remove information from the standard libraries */
 /DISCARD/ :
 {
   libc.a ( * )
   libm.a ( * )
   libgcc.a ( * )
 }

 

3.DMA用バッファをD1,D2,D3ドメインに割り当てる

ヘッダファイルなどにマクロを設定して

#define ALIGN_32BYTES_D1(buf)  buf __attribute__ ((section(".RAM_D1"))) __attribute__ ((aligned (32)))
#define ALIGN_32BYTES_D2(buf)  buf __attribute__ ((section(".RAM_D2"))) __attribute__ ((aligned (32)))
#define ALIGN_32BYTES_D3(buf)  buf __attribute__ ((section(".RAM_D3"))) __attribute__ ((aligned (32)))

プログラムの変数宣言にこのマクロをつかいます

ALIGN_32BYTES_D3(uint16_t adbuf[5]);

ALIGN_32BYTES_D2(UART_RXBUF uart_rx1);

 

stm32h743でDMAでADCを読み出すための設定

stm32cubeIDEで下記のように設定してプログラムの最初でDMA読出しをスタートすれば

HAL_ADC_Start_DMA(&hadc3, (uint32_t *)adbuf, 5);

バッファを読み出すだけで最新のAD結果を得ることが出来ます。

DMAはバックで自動的にADを読み出すのでSampling timeを短くしすぎるとプログラムの実行速度に影響があるので注意してください。

DMAの設定

YOLOv4をWindows10にインストールする

物体検出AIのフレームワークYOLOv4をWindows10にインストールしたときのメモです。

YOLOv4はc言語で記述されているディープラーニングフレームワークでインストールが簡単でlinux だけでなくWindows10でも使えるのが特徴です。

参考にしたサイト

https://www.nakasha.co.jp/future/ai/vol13_darknet_yolov4_with_opencv4.html

ソースのダウンロード先

https://github.com/AlexeyAB/darknet

インストール環境

Window 10 Pro OSビルド 19041.450
GPU:  NVIDIA GeForce GTX 750 Ti
CUDA : release 10.1, V10.1.243

手順

1.ソースをダウンロードして解凍

2.CMake-GUIで
   Configure → Configure → Generate

3. 

注記

warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。
の警告がたくさん出るが解消するための方法がわからないので放置

darknet.sln:

Debug x64の設定ではCUDA関連のエラーで構築できない
Release x64ならOK

darknet_no_gpu.sln:

Debug x64, Release x64のどちらもOK

中国の格安実装と国内メーカーによる実装の違い

Fusionの格安基板実装サービスと国内メーカーによる実装の比較

Seeed studioが基板実装サービスの宣伝が、新し物好きの私の好奇心を刺激して、中国メーカーによる実装サービスを試しているところです。

中国メーカーによる実装もピンキリ

中国の会社による実装もピンからキリまであり、同じ会社でも複数グレードのコースがあり、今試しているのは一番安い格安サービスなので中国メーカーによる実装品質が全てここで紹介する内容というわけではありません。

この記事は「格安実装サービスはどの程度使えるか?」という内容です。

中国の実装サービスによる基板の状態

Amazonで買った新しい実体顕微鏡が届きました。

7インチ マジックアーム&スーパークランプとスマホ用ホルダを組み合わせて顕微鏡撮影が出来るようにしました。

これが中国の会社による最初の実装基板です、写真で見るとわかりにくいですが端子の端面に半田クラックがあり、2割の基板に半田ゴテでの修正が必要でした。
よく見ると、あちこちに小さい半田ボールが残っています。

次が2枚目の基板です、下の端子の半田クラックは写真で見てもわかる大きさです。
こちらも半田ボールがあちこちに残っています。
2枚目の基板も2~3割の不良率でした(ただし修正可能)。

国内の会社による実装基板の状態

比較のために、製品として出荷する国内の会社で実装した基板の写真を載せておきます。

半田の状態だけでなく半田ボールなどもないきれいな仕上がりです。
右にある二本の白い線は天井の蛍光灯の映り込みです。

中国の会社による格安実装基板は試作レベルでしか使えない

見ていただいてわかるように現状では、中国の会社による格安実装基板は工業製品として出荷できるレベルではありません。

ただ、中国の会社レベルは日進月歩で変化していますし、試作や教育分野ではコスト面と部品入手を一任できるメリットが大きいので品質差をわきまえて中国の会社による実装も上手に活用していくのが得策です。