STM32F7を使ってみる4 -CPUキャッシュとDMAを考慮する-
前回DMA転送がうまくいかなかったと抜かしていましたが原因は至って単純な
もので私にCPUキャッシュについての知識が無かっただけでした!!!!!
めでたしめでたし♥
20231123追:
古いCortex-M7コアにはキャッシュ周りにバグがあります!!
こちらのエントリも必ず見てください!!1!!1!!
20231123追:
今回は上の三行で終わる内容ですが前回の記事そのものがCortex-M7アーキテク
チャを全く理解してないおまぬけなねむいさんのままで終わってしまう(あたしはまだ
終わってはない!)のでもう少し突っ込んで解説したいと思います。
STM32F7にはI-CacheとD-Cacheの2つのレベル1キャッシュメモリがありこれらを
有効化させることによりリアルタイム性が落ちる代わりに全体の処理の高速化を
図っています。今回はデータ用キャッシュメモリD-Cacheに着目します。
今回の記事を書くにあたってユークエストのビリー様のサイトを参考にさせていただきました。
私のいつものではプログラム開始時にI-CacheとD-Cacheを有効にし、さらにMPUで
SRAM1,2領域(256kByte分)のWriteThroughを有効にしています。CPUからのこの
SRAM領域(以下本メモリ)への読み書きはWriteThroughによって常に本メモリと
D-Cacheの一貫性(Cache Coherency)が保たれています。WriteBackよりも多少は
処理速度は落ちますがそれでもD-Cacheの恩恵に与かれるので確実で強力です。
しかしながらこの関係が破れるのがDMA転送をする時です。
DMAコントローラはキャッシュメモリを介さないのでD-Cacheと本メモリの一貫性を
保てなくなりDMA転送後に本メモリから読みだしたはずの本当のデータはD-Cache
に残った古いデータで正常に読みだせない&転送がコケる(ように見えた)という事に
なります。以下にlibjpegで画像をデコードした際の実例を示します。
こちらは虹裏的美少女画像をSDMMCのデータ転送にDMAを一切使わずFIFOのポーリ
ングで読みだした所の写真です。右下に表示にデコード完了に掛かった時間を表示して
います。I/D-Cacheは有効です。
無対策でDMAで読みだした時の写真です。途中でデータがおかしくなってひでぶ
しているのが分かります。上記のとおりD-Cacheに残った古いデータのせいでめちゃ
くちゃになってる訳ですが、当たり前ですが表示にすら至らないケースもあります。
その前に脇道にそれますがlibjpegとFatFsを結合している関数について、この関数
内ではlibjpeg側で先にmallocで取得したデータ読み出し用バッファをDMAの読み出し
先にしてしまいます。
つまり私のいつもので使うFatFsのデータ転送用汎用バッファBuff(上記画像参照)が
どのメモリ領域にいるかは関係がなく、リンカスクリプトでHEAP領域にD-Cacheの影響
を受けるSRAM1,2を割り当てているとDMA転送時の上記の問題に思い切り引っ掛かる
ことになります。それを踏まえたうえで本題の比較に入ります。
プログラム開始時の時点でD-Cacheそのものを無効にすると当たり前ですがデータ
の齟齬が発生する余地が全く無くなりますので表示がおかしくなることはありません。
しかしながらパフォーマンスはガタ落ちになります。これじゃF7使う価値がないです。
対策その1です。
FatFsの汎用バッファをキャッシュの影響を受けないDTCM領域に配置し、さらにDMAの
4バイトアライメント対策もDTCMの1セクタバッファでフォローする作戦です!
CPUコアと同速度で動くDTCMでキャッシュの影響とレイテンシの不確実性を最小限に
でき、確実な転送が可能です!!
しかしこの方法は以下の制約を受けるのでご留意願います。
1.リンカスクリプトでDATA,BSS,STACK領域を必ずDTCMに割り当てるべし。
2.mallocで引っ張ってきたメモリドレスがDTCMのアドレスじゃなかった場合の
対処を講じる必要がある。実際は読み書き元のアドレスを検知してDTCMの1セクタ
事の読み書きに変えるかキャッシュコントロール関数を使用するかです。
私のSTM32F7向けのいつものはこの対策1を施しておあります。
対策その2です。
DMA転送する前にD-Cacheの無効(Invalidate)だけを行います。CMSISのヘッダライ
ブラリでは上記の無効にする関数が用意されています。STM32F7のキャッシュサイズ
は4kByteでlibjpegの一度に読みだすサイズもデフォルトでは4kByteとなってます。
(注:Cortex-M7のキャッシュは1ライン32byte*128本で合計4096Byte)
D-Cacheの1ラインごとにInvalidateする関数もありますが今回は読み出しサイズが
キャッシュサイズと同じなので全部Invalidateする関数を呼び出してます。
SDMMCのDMA転送を行う関数の頭にSCB_InvalidateDCache()を置いて実行してい
ますが対策その1よりも若干遅くなっています。
そういえば・・・Disableも無効って意味なんですがあちらさんではどう
使いわけてるんでしょ…
対策その3です。
DMA転送する前にD-CacheのInvalidateとCleanを行います。
SCB_CleanInvalidateDCache()を呼び出しますが必然的に対策その2よりもさらに
遅くなっています。
対策その2と3は単純にCMSISヘッダライブラリの関数を実行すればいいという訳では
なく、DMA元/先として使うバッファのアライメントとサイズに制約があります。
D-Cacheのキャッシュラインのサイズにアライメントを合わせ、なおかつそのサイズの
整数倍にしないとやっぱりデータの齟齬が起こってしまいます。
特に読み出し時はDMA用に確保したバッファの近辺のアドレスに配置されている変数
までしっかり破壊してくれやがります。STM32F7の場合は1キャッシュライン当たり
32Byteの固定値となっているので32バイトのアラインメント且つデータサイズが32の
倍数になる必要があります。
もしバッファ用のメモリ領域が上の条件を満たさない場合はアライメントとデータサイズ
の丸め込みを行う必要性があり更にオーバヘッドが増えます。RTOS向けのデバイス
ドライバを作成される際はこの点も考慮する必要があります。
以上の点を踏まえると別に無理してDMAしなくてもいいんじゃないかと思われるかも
しれませんがそれではロマンが無いので是が非でもDMAらせていただきます!
そんなわけでD-Cacheを考慮した修正版のいつものをあげておきます・・・
おまけ
libpngやlibjpegは無対策でも平気だったのですが何故ひでぶしないで平気だったのかも
調べてみました。
giflibはSDMMCのブロック転送時にfptrがクラスタの境界になく、その際の一時
転送先がDTCM領域のFatFsオブジェクト内(のwin配列)に確保されています。
つまり対策その1とほぼ同じ事をFatFsライブラリ内でやってくれているわけです。
libpngもgiflibと同様になっています。
-
免責・連絡先は↑のリンクを
↓SNSもやってます↓
powered by まめわざ- ARM/STM32 (116)
- OpenOCD (27)
- ARM/NxP (34)
- ARM/Cypress (5)
- ARM/Others (3)
- ARM/Raspi (1)
- AVR (13)
- FPGA (4)
- GPS/GNSS (19)
- MISC (81)
- STM8 (2)
- Wirelessなアレ (16)
- おきぱ (1)
- ブラウザベンチマーク (28)
- 日本の自然歩道 (25)
- STM32U0はぢめました
⇒ ねむい (08/07) - STM32U0はぢめました
⇒ ひかわ (07/28) - STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
⇒ ねむい (05/17) - STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
⇒ どじょりん (05/16) - STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
⇒ どじょりん (05/16) - いろいろ試す61(と今年の反省会)
⇒ ねむい (01/02) - いろいろ試す61(と今年の反省会)
⇒ ひかわ (01/02) - いろいろ試す61(と今年の反省会)
⇒ ひかわ (01/01) - STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
⇒ ねむい (12/31) - STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
⇒ ひかわ (12/31)
- October 2024 (1)
- September 2024 (1)
- August 2024 (1)
- July 2024 (1)
- June 2024 (1)
- May 2024 (1)
- April 2024 (1)
- March 2024 (1)
- February 2024 (2)
- January 2024 (1)
- December 2023 (4)
- November 2023 (2)
- October 2023 (2)
- September 2023 (1)
- August 2023 (2)
- July 2023 (1)
- June 2023 (2)
- May 2023 (3)
- April 2023 (1)
- March 2023 (1)
- February 2023 (1)
- January 2023 (1)
- December 2022 (2)
- November 2022 (1)
- October 2022 (1)
- September 2022 (1)
- August 2022 (1)
- July 2022 (1)
- June 2022 (1)
- May 2022 (1)
- April 2022 (1)
- March 2022 (1)
- February 2022 (1)
- January 2022 (1)
- December 2021 (2)
- November 2021 (2)
- October 2021 (1)
- September 2021 (1)
- August 2021 (1)
- July 2021 (1)
- June 2021 (1)
- May 2021 (1)
- April 2021 (1)
- March 2021 (1)
- February 2021 (1)
- January 2021 (1)
- December 2020 (3)
- November 2020 (1)
- October 2020 (1)
- September 2020 (1)
- August 2020 (1)
- July 2020 (1)
- June 2020 (2)
- May 2020 (1)
- April 2020 (1)
- March 2020 (1)
- February 2020 (1)
- January 2020 (1)
- December 2019 (3)
- November 2019 (1)
- October 2019 (1)
- September 2019 (2)
- August 2019 (1)
- July 2019 (1)
- June 2019 (1)
- May 2019 (1)
- April 2019 (1)
- March 2019 (1)
- February 2019 (1)
- January 2019 (1)
- December 2018 (3)
- November 2018 (2)
- October 2018 (1)
- September 2018 (1)
- August 2018 (1)
- July 2018 (1)
- June 2018 (1)
- May 2018 (1)
- April 2018 (2)
- March 2018 (1)
- February 2018 (1)
- January 2018 (1)
- December 2017 (2)
- November 2017 (2)
- October 2017 (1)
- September 2017 (1)
- August 2017 (1)
- July 2017 (1)
- June 2017 (1)
- May 2017 (1)
- April 2017 (1)
- March 2017 (2)
- February 2017 (2)
- January 2017 (2)
- December 2016 (7)
- November 2016 (2)
- October 2016 (2)
- September 2016 (1)
- August 2016 (1)
- July 2016 (1)
- June 2016 (1)
- May 2016 (2)
- April 2016 (1)
- March 2016 (2)
- February 2016 (1)
- January 2016 (1)
- December 2015 (3)
- November 2015 (1)
- October 2015 (3)
- September 2015 (2)
- August 2015 (2)
- July 2015 (3)
- June 2015 (3)
- May 2015 (4)
- April 2015 (2)
- March 2015 (4)
- February 2015 (1)
- January 2015 (3)
- December 2014 (3)
- November 2014 (2)
- October 2014 (1)
- September 2014 (2)
- August 2014 (2)
- July 2014 (3)
- June 2014 (2)
- May 2014 (1)
- April 2014 (1)
- March 2014 (4)
- February 2014 (4)
- January 2014 (3)
- December 2013 (5)
- November 2013 (4)
- October 2013 (3)
- September 2013 (2)
- August 2013 (2)
- July 2013 (2)
- June 2013 (3)
- May 2013 (2)
- April 2013 (2)
- March 2013 (2)
- February 2013 (2)
- January 2013 (3)
- December 2012 (4)
- November 2012 (2)
- October 2012 (2)
- September 2012 (4)
- August 2012 (1)
- July 2012 (3)
- June 2012 (2)
- May 2012 (3)
- April 2012 (3)
- March 2012 (2)
- February 2012 (3)
- January 2012 (3)
- December 2011 (5)
- November 2011 (3)
- October 2011 (2)
- September 2011 (2)
- August 2011 (2)
- July 2011 (2)
- June 2011 (2)
- May 2011 (2)
- April 2011 (2)
- March 2011 (2)
- February 2011 (2)
- January 2011 (3)
- December 2010 (7)
- November 2010 (1)
- October 2010 (1)
- September 2010 (1)
- August 2010 (3)
- July 2010 (4)
- May 2010 (1)
- April 2010 (2)
- March 2010 (2)
- February 2010 (2)
- January 2010 (3)
- December 2009 (3)
- November 2009 (8)
- October 2009 (7)
- September 2009 (5)
- August 2009 (4)
- July 2009 (6)
- June 2009 (6)
- May 2009 (14)
- January 1970 (1)
Copyright(C) B-Blog project All rights reserved.