STM32F7を使ってみる3 -FatFsとLCDコントローラを動かす-

前回ねむいさんはUARTとFatFsをデモを参考にSDカード向けに組み替えて動作
せしめるところまで来ました。調子に乗ってDMA化しようと試みたのですが
なんでか正しく転送出来ませんでした

ねむいさん真っ先に悪名高いHALライブラリにバグがあると思って調べまくり
ました。SPLで組んだF4のSDIOの転送するルーチンやDMAの処理の部分などを
穴の開くほど見比べたのですがこれと言って悪い箇所が見当たらず、まさか
エラッタかと思ってエラッタシートやフォーラムもしらみつぶしに見たのですが
そもそもまだF7が広まってない段階なので手がかりすら見つかりませんでした。



20150807追:
ここまで読んで「あ、こいつキャッシュのこと理解して無い馬鹿野郎だ」と思った
方はさっさと次のエントリに進んでくだち
20150807追:




DMA転送用のバッファメモリをDTCMやSRAM2や外部SDRAMとかにおいてもダメダメ
で困り果てていたのですがF7のデモがDTCMを含めた複雑な構成のSRAMを単純に
320kbyteのでかいSRAMとして扱っていたのを思い出し、ねむいさんも細かい
RAMの割り振りをやめてデモと同じようにしてみました。


するとDMAでもちゃんと転送できた。


ぇえ〜〜〜何が違うのよ!とぶちぶち言いながら何が足を引っ張っているのかの
切り分けを進めていくと最終的にFatFsの構造体をDTCMに配置していないと、
DMAがコケる
ことが分かりました。デモではリンカスクリプトでDTCMの領域の
0x02000000から各種変数が割り当てられるため、問題だったSRAM1領域以降の
RAMまでは使用されていないことが分かりました。

データ用バッファとか話が分かるのですがなんでFatFsの構造体がDTCM領域に
無いと何故DMA転送できないのか理由が全く分かりません。F7はまだ世に出た
ばっかでエラッタも未知のものがたくさんあるでしょうから今は深追いは止め
てその先の作業に専念することにしました(しかしこのあとさらなる罠が)。
20150805追:
単にD-Cacheの取り扱いがわかってなかっただけでしたすみません。




と言う訳でFIFOポーリング版とDMA版の読み取り速度の比較を行ってみました。
ポーリング版でも効率化されてますのでDMAと遜色なくなってますね〜。ていうか早い
勿論条件は過去と同じ、スピードは双方ともSDHighSpeedModeにしております。
20150807追:
上の結果ですがPLLSAIの設定間違っていて実際はSDIO_CLK=44MHzくらいで測定
してましたすみません!!


↑PLLSAIの設定を正しく行ってSDIO_CLK=48MHzで読み出したときの
 真の速度です。



SDRAMを使用するとSTM32F7の最大クロック周波数は200MHzまでとなってしまい、
この時のSDMMCのクロックはSYSCLKから供給していると単純計算で48MHzよりも
若干低下してしまうのですがSAI用のPLLをSDMMCのクロック源とすることで48MHz
きっちり動作させることができます。



ひとまずFatFsはめどがついたのでお次はLCDコントローラ(LTDC)です。こちらも
以前STM32F429Discoveryで予習していたはずなのですがSPLとまっっったく構造が
代わっていたので難儀しました。

LTDCについては各種設定を行った後フレームバッファとするSRAM及びSDRAMの
ポインタを参照すれば何とかいつも通りに色を出せたのですが問題はDMA2Dでした。
ああでもないこうでもないを重ねてようやくF429で出来たのと同じように動作させる
ことができるようになりました。結局元のF4のSPLのコードを穴の開くほど読み込んで
CubeF7とどう違うのかの地道な切り分けです。

以下にDMA2D版のDisplay_wr_block_if()のF4版SPLとCubeF7の違いを示します。
両者とも色深度はRGB565の16bppです。


inline void Display_wr_block_if(uint8_t *p,unsigned int cnt)
{
/* Set Display Pointer */
lcd_c_buf_ptr = lcd_f_buf_ptr + 2*(lcdc.x + MAX_X*lcdc.y);

/* configure DMA2D */
DMA2D_DeInit();
DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M_PFC;
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = (uint32_t)lcd_c_buf_ptr;
DMA2D_InitStruct.DMA2D_OutputOffset = (MAX_X - ((lcdc.width+1) - lcdc.x));
DMA2D_InitStruct.DMA2D_NumberOfLine = (lcdc.height+1) -lcdc.y;
DMA2D_InitStruct.DMA2D_PixelPerLine = (lcdc.width+1) -lcdc.x;
DMA2D_Init(&DMA2D_InitStruct);

/* Configure default values for foreground */
DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
DMA2D_FG_InitStruct.DMA2D_FGMA = (uint32_t)p;
DMA2D_FGConfig(&DMA2D_FG_InitStruct);

/* Start Transfer */
DMA2D_StartTransfer();

/* Wait for CTC Flag activation */
while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET){}
}

↑F429の


inline void Display_wr_block_if(uint8_t *p,unsigned int cnt)
{
/* Set Display Pointer */
lcd_c_buf_ptr = lcd_f_buf_ptr + 2*(lcdc.x + MAX_X*lcdc.y);

/* configure DMA2D */
Dma2dHandle.Init.Mode = DMA2D_M2M_PFC; /* memory to memory with PFC */
Dma2dHandle.Init.OutputOffset = (MAX_X - ((lcdc.width+1) - lcdc.x));
/* DMA2D Initialisation */
if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK)
{
/* Initialization Error */
while(1);
}

/* Start DMA2D transfer */
if(HAL_DMA2D_Start_IT(&Dma2dHandle,
/* Source Buffer */
(uint32_t)p,
/* Dist Buffer */
(uint32_t)lcd_c_buf_ptr,
/* width in pixels */
((lcdc.width+1) -lcdc.x),
/* height in pixels */
((lcdc.height+1) -lcdc.y))
!= HAL_OK)
{
/* Initialization Error */
while(1);
}
}

↑F7の


DMA2Dを利用したレクタングルの塗りつぶし等の図形表現も無事再現できました。
F429で出来てたことをF7で再び出来るようになるまで1週間以上かかりやがりま
したがCubeF7が抽象化しすぎて逆にプログラムの流れが分かりづらいとかそも
そも作りこみが甘くbuggyとか公式のフォーラムでも未だに非難GOGOでF7版SPL
くだちとかいろいろ言いたいのですがまぁそれは置いといて…。


UART,FatFs,ディスプレイまで出来たら既にねむいさんのいつものができたと言っても
過言ではありません。ChaNさんの2009年作のLPC2388向けのデモをベースに足かけ
6年…もう6ねn…n…グハッ!!!







失礼、ちょっとむせました。

画像はpngないないさん♥
libjpeg,giflib,libpng3つの画像ライブラリを用いたデコードも紆余曲折ありましたが
いつも通り出来るようになりました♥
こちらについては話が長くなるのでDMAする時のD-Cacheの取り扱いと合わせて
次回解説させていただきます。


そういうわけでSDMMCのDMA転送でだいぶ足止め喰らいましたがようやく形になって
来ましたのでここでいつものの公開をさせていただきます。残るは容量性タッチパネル
の処理の実装ですがこちらも初めての分野なのでじっっっくりと取り組んでいこうと
思います。


STM32F746G-Discoveryのいつものはこちら

STM32F7を使ってみる2 -STM32CubeF7移植への道-

STM32F7シリーズは今年から量産開始した新しいマイコンです。つまり昔から
STM32を昔から弄ってる人にとってはおなじみだったStandard Peripheral Library
(=SPL)のF7版なぞ影も形もなく、STM32CubeF7ライブラリ通称HALライブラリ
しか存在いたしません!

ChaNさんクラスの実力がある人ならリファレンスマニュアルからレジスタ構成を
引っ張ってきて自前のペリフェラルライブラリこさえるのでしょうけどねむいさんに
そんな力があるはずもなくなすすべもなくSTマイクロのエコシステムの一部に
とりこまれてしま…ぅ・・・


まだまだだぁ!!!

幸いにもCubeF7ライブラリの中にはSW4STM32(System Workbench for STM32)
なるEclipseベースのフリーのIDEがあり、コンパイラはGCCを使用していますので
これを分析することによって私のコマンドライン&makeの環境移植へのとっかかり
を見つけることが出来ました。
ところでなんでEclipse使ってるのに全身から血を吹き出して死なないのかこの
嘘吐きめと突っ込みたいでしょうが私はメーカーお仕着せの各種設定完了済の
Eclipseのカスタム版IDEでは無傷です。あくまで死ぬのは未設定の素のEclipseで
攻撃された時だけです。あといないさんがスカートをたくし上げて下着を見せてるイラストを
見せられただけでも死ぬので絶対に見せないでください

絶対にですよぅ!!!!






それはおいといてSTM32F7-Discoveryを使ってF7版のいつものの構築に移ります。
昨年の時点でNucleo系の板はSPLからHALライブラリに引っ越ししておりました
しかしあくまでUARTやI2Cと言った基本のライブラリを動かす程度に留まって
いたのですが今回はSDRAMやFatFsなどを動かすところまで行きます。


STM32F7になってメモリ構成がF4よりもはるかに複雑になりましたが基本は
全く変わっていません。恐れずにF4と同じようにプランを練っていきました。

TCMのうちユーザーが触ることができるDTCMはF4ではできなかったDMAができる
ようになったので細かいことは気にせずスタック/Auto変数領域に割り振る
ことができます。CubeF7のExampleではDTCMの初めからメインSRAMの終わりまで
をまるまる一本の巨大SRAMとして使っていますので細かいこと気にするなと
言うことなのでしょう。実際DTCM〜SRAM2までリニアに繋がってますし。
↑実はこれが伏線だった…


そんなわけでいつものGCCのビルド環境のひな形が出来ました

先ずは基本の"き"LED点滅とUARTから。
LEDはF7-Disacovery上ではArduinoUNOライクなコネクタピンのSCKに
相当するPI1です。

なお、昨年くらいのCubeF4のアップデートで気づいたのですがGPIOのビット
単位でセット/リセットが可能なレジスタSBRR/BRRと言うのが昔はおなじみ
だったと思いますがそれが廃止され32bitのSBRRのみとなってやがります###
ビット単位でI/Oをやり取りする際にこれは超不便且つビットアクセスのための
新しくできたHALライブラリのオーバヘッドがでかすぎるので旧来のGPIOの
構造体を作って昔と同じように16bit幅のSBRR/BRRレジスタをアクセス
できるようにしました。

UARTはSTLink/V2-1のVCP入出力が繋がるUSART1ポートのPA9(TX)、そして
GPIOB7(RX)です。RXピンはおなじみのPA10じゃないのでご注意を!

と言うわけでこの2つはF4版NUCELOを参考にF7用にあてはめるだけでOKでした。


もちろんprintf関数などのnewlibの関数群との結合も余裕です★



ここでちょっと注意ですがSTLink/V2-1でVCPを使う際に特定のUSB3.0
ホストに差すとSTLink/V2-1側から送信するUARTの信号が正常に出力
されない場合があることを発見しました。
その特定のUSBホストと言うのはFL1100なのですが上記の画像のように
めちゃくちゃな信号が出力されてSTM32F7側と正常に通信ができません。
もしUSB3.0ポートで上手くいかない場合はUSB2.0ポートに差し直して
試してみてください。


お次はSDRAMです、F7-Discoveryには128MbitのSDRAMが搭載されています。
こちらもBSPの初期化コードを参考にねむいさんの環境に嵌めて行って危なげなく
動作せしめることが出来ました。このボードにおいてはSDRAMBank1に配置されて
いて0xC0000000が開始アドレスとなっています。

STM32F7でFMCを使ってSDRAMを使用する場合、F7側はデータバスが16bit分
しかないので32bitの変数のアクセスはAHBバスで16*2bitに分割転送されます。
そんなわけでこのボード上では上位16bit分のデータバスを男らしくバッサリ
捨てており容量は128MBitありますが実質64MBit分しか使えませんorz
また、Example曰く実装されたSDRAMが安定動作するシステムクロックの
上限は200MHz、その時のSDRAMCLKの上限は100MHzになるので、
(↑根拠としてSTM32F7のデータシートに下記の記述がありました。
 For 3.0 V≤ VDD≤ 3.6 V, maximum FMC_SDCLK = 100 MHz at CL=20 pF (on FMC_SDCLK).)
単純計算で100MHz*16=1600MBps
が理論値となります。なんかちょっともったいない使い方ですね…。

前回の記事でたけさんと言う方からリクエスト貰いましたのでSDRAMのR/W
性能を測定してみました。4MByte分(下述)を16bit変数単位で読み書きした値です。
D/I-Cacheは有効にしていますが妙に数値が低いのは私のコーディングが悪い
せいでしょうか・・・


最後にFatFsです。CubeF7謹製のFatFsのローレベルドライバはやたら凝っていて
USB-OTGのUSB-MSCの接続も想定したつくりになっています。FatFSで必須な
関数群はFATFS_LinkDriverなる関数で結合する仕組みとなっています。
今回からはSTのスタイルに倣ってそれを積極的に使うようにしました。
といっても私のプロジェクト向けにほんの少しの変更をしただけですが。


まだTFT-LCDのドライブまでは進めてないのでUARTからのコマンドでFatFsの
動作を確認しました。F7-DiscoveryではSDIO改めSDMMCインターフェースが
出ていてSDカードからのデータを高速にやり取りできます。


いつものごとく読み出し速度を調べてみました。CubeF7のExampleではSDMMCの
クロックは潰しの効くNomalMode(25MHz以下)に抑えられているのでF4の25MHzと
さほど変わりませんね。


CubeF7のライブラリを調べているとDMAは全く使用してないFIFOポーリングで
読み書きを行っていることが分かりましたがHALライブラリにはDMAを使用する
関数も用意されていてほんの少しの改修でDMA化できるので試してみました

が…!



なん…だと…!?


つづく!

STM32F7はぢめました

昨年秋にプレスリリースで発表されたSTM32F7ですが私がESP-ROOM-02弄り
夢中になってる間にひっそりと市場に流通しておりました。
ヒを見てたら国内外問わず既に入手してOpenOCDでバリバリ使い倒してる人たちもいて
STM32好きの私としてはすっかり流れに取り残された感じですがDigiKeyで大量に在庫
していたので私も一つ購入してみました。



目の前に現れたSTM32F7-Discoveryは私の知ってるDiscovery系のキットの想像を
超えた液晶もSDカードスロットも外部SDRAMもQSPI-ROMもついた夢の全部載せでした!
ちなみに液晶のタッチパネルは抵抗膜式ではなくなんと静電容量式です!
なんてゴージャスな…


Cortex-M7コアを持つSTM32F746NGH6が搭載されています。スペックについては昨年
秋も触れましたが量産開始後に最大動作周波数が200->216MHzにパワーアップして
ます。デバッガはSTLinkV2-1が搭載されています。


当然のごとくSDRAMが搭載されています。Micronの128MBitのSDRAMです。


同じくSTM32F7シリーズの目玉の一つQ(uad)SPI-ROMです。LPC4000シリーズの
SPIFIと同じくリニアなアクセスができるのが特徴です。FontX2ファイル等の
大規模データは一切合財ここにぶち込みましょう!


また、Ethernet用のPHYも搭載です。接続するピン数が少ないRMII方式で
STM32F7と接続されています。


さらにUSB-HighSpeed用のPHYまでついています!!こちらはULPIで接続されます。
後で触れますがUSBメモリを接続するのにちょうど良いですね。


さらにさらにI2S-Codecも搭載されています!!!STM32F4でも搭載されていましたが
同じように"いつもの"が出来そうです。SAIインターフェースで接続されています。


そしてこれだけそろってお値段はなななんと$50ですよ奥さん!!(DigiKeyより)
こんな時代になったのですね…2009年のころは全く考えられなかったのですが…
しみじみ












しみじみするのはその辺にして早速いじってみました。
STLink側のUSB-miniBケーブルをPCと接続するとドライバを読み込んだ後STM32F7
側にも電源が供給されてプログラムが走り出します。
すぐにナウいロゴが出てきます。


すぐにメニュー画面になり、タップでいくつかのアプリケーションが選べるように
なっています。しかもCPUの負荷率もリアルタイムで表示されます。


200MHzで動いているので結構発熱します。F4シリーズと違ってΔTは10度以上あると
思ってください。それでも他の品種の同周波数のものと比べると低いほうですが。


静電容量式タッチパネル(CTP)なので物理で押してもだめです。指で操作しましょ。


先ずは"audioplayer"です。USBメモリに仕込んだwaveファイルを読み込んで再生し
ます。デモはHS側のUSB-OTGだけしか反応しませんのでご注意ください。USB-FSや
SDカードは未実装のようです。


再生してる所です。音量調節が狭くて音量を上げようとすると指がメニューに
あたってしまって最初の画面に戻ってしまいがちです。どうでもいいですが。


infoメニューでは現在の動作周波数やファームウエアのバージョンが表示されます、
ファームウェアとやらは勿論STM32CubeF7の事です…。
どうでもいいことですがたまに異様にCPU負荷が100%になって動作が異様にもっさり
したり固まったりするのですが私の操作が早すぎるせいなのでしょうか???




さて、デモプログラムを触るのはこの辺にしてねむいさんのいつものの準備を、
GCCのコマンドラインビルドできる環境を固めて行こうと思います。OpenOCDはまだ
レビュー段階ですがSTM32F7フラッシュ書き込み用パッチが公開されています。

糞ややこしいのですがパッチはCortex-M7用とSTM32F7用の2種類か必要でした
http://openocd.zylin.com/#/c/2786/
http://openocd.zylin.com/#/c/2784/
http://openocd.zylin.com/#/c/2753/4
http://openocd.zylin.com/#/c/2753/5
2753は要注意です。#5のパッチだけあててもF7対応になりません!

まぁやり方さえわかればビルドはいつもどおりなのでらくちんです★
バイナリは既にSTM32F7対応に更新してあります♥
cfgファイル群も更新しましたのでどうぞ。


STLink/V2-1もファームがM11に更新されていますので事前にアップデートして
おきましょう。STLink-Utilityも3.6に更新しておいてください
20150714追:
M11に更新しないとOpenOCDで書き込むことができませんのでご注意!!!!



まだF7向けのGCCプロジェクトはこさえていないので記事を書く2日前に1.0.1に
アップデートしたばっかリのCubeF7のF7Discovery向けのデモプログラムの
ビルド済みhexファイルをOpenOCDから焼いてみます。その前にSTLink-Utilityで
接続し、デモプログラムのhexを読み込ませてみました


このhexファイル、19MByteも有るのですがフォントと画像データがあるQSPIの領域も
含まれているようです(0x90000000以降の領域)。まだ外付けのQSPIの読み書きには
対応していないので内蔵フラッシュしか書き込むことができませんがQSPIに仕込んで
あるデータはシカトして内蔵フラッシュのだけ無理やり更新できます。


STLink-UtilityのExternalFlashLoaderにF7Discovery向けのQSPIドライバ無いんです
けぉ・・・###それはおいといてOpenOCDに話を移します!!!!


案の定QSPIの領域ではエラーが出ますが何とかフラッシュは書き込みできてます。


無事ファームウエアをV1.0.1に変更することができました。



そんなわけでSTM32F7をほんとに触りだけでしたが触れてみました。
これからいつものビルド環境に合わせたプロジェクト作りを進めて行きたいと思います。
F4の時にCubeF4向けにペリフェラルドライバの移植を試みましたが結局UARTまでしか
実装できなかったので今度こそ本気出します!!
(2年ぶり4度目)

Go to top of page