STM32L5を使ってみる2 -FatFsその他の実装-
●いつものやつを実装しよう
前回は144Pin版NUCLEO基板の下駄基板のビジュアルだけ紹介しましたが、
今回はそれを動かすためのファームウエアの要所を紹介していこうと思います。
ねむいさんの"いつもの"ことChaN師のFatFs実装を中心としております。
以下、STM32L5-NUCLEOのFatFs実装例のプロジェクトの要点を掻い摘んで
解説していきたいと思います。
●GCCビルドのためのCortex-M33向けオプション
先ずはmakefileを見ていただいたらお分かりと思いますがCortex-M33は
基本的にCortex-M4Fの進化版と思って頂けたらよいと思います。
GCCコンパイラに与えるCortex-M33コア向けオプションは以下になります。
-mcpu=cortex-m33 -mtune=cortex-m33 -mfix-cmse-cve-2021-35465-mfix-cmse-cve-2021-35465とかいうのはArmv8-Mコアの脆弱性対策です。
2023年現在の最新のGCCコンパイラはデフォルトでONになっておりいちいち
入れる必要はないかもしれませんが念のため明示してます。
●基本の"き"、タイマーとUARTの実装
STM32に代表されるCortex-M系のコアはほぼすべてにSystickタイマーが
標準装備されております。こちらを1mSecウエイト用のタイマーとして、一方
マイコン周辺機器のタイマー機能を利用してuSecオーダーのタイマーを実装します。
今回はuSec用にはTIM5を利用しました。
以下systick.cより抜粋
	/* Making MicroSecond-Order Timer uses general purpose timer! */
	/* Enable timer clock */
	USEC_TIMx_CLKEN();
	/* calculate TIMx(2 or 5) Prescaler clock(APB1) */
	if(RCC->CFGR & RCC_CFGR_PPRE1){
		if((RCC->CFGR & RCC_CFGR_PPRE1) == RCC_HCLK_DIV2){
			cal_usec_divide = SystemCoreClock/2;   	/* (HCLK(=SYSCLK)*2 */
		}
		else if((RCC->CFGR & RCC_CFGR_PPRE1) == RCC_HCLK_DIV4){
			cal_usec_divide = SystemCoreClock/4; 	/* (HCLK(=SYSCLK)*4)*2 */
		}
		else if((RCC->CFGR & RCC_CFGR_PPRE1) == RCC_HCLK_DIV8){
			cal_usec_divide = SystemCoreClock/8; 	/* (HCLK(=SYSCLK)*8)*2 */
		}
		else if((RCC->CFGR & RCC_CFGR_PPRE1) == RCC_HCLK_DIV16){
			cal_usec_divide = SystemCoreClock/16; 	/* (HCLK(=SYSCLK)*16)*2 */
		}
	}
	
	/* usec wait timer settings */
	TimHandle.Instance 				 = USEC_TIMx;
	TimHandle.Init.Period            = UINT32_MAX;
	TimHandle.Init.Prescaler         = ((cal_usec_divide)/USEC_INTERVAL) - 1;
	TimHandle.Init.ClockDivision     = 0;
	TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
	TimHandle.Init.RepetitionCounter = 0;
	TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
	if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK)
	{
		/* Capture error */ 
		while (1);
	}
	
	USEC_TIMx->CR1 &= ~(TIM_CR1_UIFREMAP); /* Disable UIF Remap(Must Need!) */
	HAL_TIM_Base_Start(&TimHandle);最近のHALライブラリは"AutoReloadPreload"構造体が追加されているので
移植の際はご注意ください。また,UIFRemapビットにもご注意ください。
UARTについてはNUCLEO-L552ZE-Q基板上ではSTLinkのVCPとはLPUART
なるもので接続されております。一般のUARTとは多少違いがありますが
やることは同じです。LPUART1、GPIOG7,8をTX,RXとします。
一応LPUART以外のポートも使用できるようにしておりますので詳細は
uart.cupport.cを参照願います(丸投げ)
っとその前にLPUART1を使う際はLPUART1へのクロック供給のほかに
"HAL_PWREx_EnableVddIO2()"の実行も忘れないようにしてください。
またリングバッファによるノンブロッキング送受信なのはいつも通り
なのでスムーズにデータのやり取りができると思います。
●SDMMCドライバの実装・FatFsとの結合
STM32L5にはSDMMCがありますのでこれを実装しますが数年前STM32H7に
実装したSDMMCのドライバをスライド移植するだけのお手軽です☆
ぶっちゃけ今回の移植作業で一番楽でした。

一応使用上の注意なのですがSTM32H7と同じくSTM32L5のSDMMCはDDR
モードが使用可能ですがSDMMCに供給するクロックがバイパスされて
いないと使用不可となりますのでご注意ください。
ねむいさんの作例ではデフォルトではHSI48をSDMMCにバイパスなしで
供給しているためDDRで使用することができませんorz


もしDDR対応のeMMCをお持ちの方はコアクロックを110MHzから100MHzで
動かすとHSI48を使わずコアクロックをSDMMCのクロックにするよう
切り替えますので試してみてください。
STM32L5の最大動作クロックは110MHzなんですけどこういう制約が色々
あって100MHzで動かすほうがよっぽど有利なんですよね〜
100MHzとか昨今のマイコンでは遅い部類のクロックですがまぁ初代の
STM32F1とかのMAX72MHz動作と比べたら(消費電力も合間見ると)雲泥の
差ですがすっかり贅沢になってしまいましたね〜
STM32H7の実装でも実はひっそり最高速の480MHz対応してますが
こちらもいずれ紹介しようと思います。
●SPIとシリアル接続TFT-LCD
STM32L5のSPIモジュールも言ったって普通のSPIなので実装は容易
でした…が、DMAのほうはちょっと一癖ありました。
ねむいさんが知ってる従来のDMAではなくってDMAのチャネルがマルチ
プレクスされていて柔軟な設定ができるようになっており、逆に扱いに
苦労しましたがExampleを参考に何とかSPIでDMAを吐けるようになって
おります。以下にDMAMUXの設定を抜粋しておきます。
全体は./lib/display/mcu_depend/display_if_basis.cを参照のこと。
#ifdef USE_DISPLAY_DMA_TRANSFER
	/* DMA controller clock enable */
	__HAL_RCC_DMAMUX1_CLK_ENABLE();
	__HAL_RCC_DMA1_CLK_ENABLE();
	/* Configure DMA request LcdDmaHandle */
	LcdDmaHandle.Instance 					= SPILCD_DMA_CHANNEL;
    LcdDmaHandle.Init.Request 				= SPILCD_DMA_REQEST;
    LcdDmaHandle.Init.Direction 			= DMA_MEMORY_TO_PERIPH;
    LcdDmaHandle.Init.PeriphInc 			= DMA_PINC_DISABLE;
    LcdDmaHandle.Init.MemInc 				= DMA_MINC_ENABLE;
    LcdDmaHandle.Init.PeriphDataAlignment 	= DMA_PDATAALIGN_BYTE;
    LcdDmaHandle.Init.MemDataAlignment 		= DMA_MDATAALIGN_BYTE;
    LcdDmaHandle.Init.Mode 					= DMA_NORMAL;
    LcdDmaHandle.Init.Priority 				= DMA_PRIORITY_MEDIUM;
    if (HAL_DMA_Init(&LcdDmaHandle) != HAL_OK)
    {
		for(;;){
			__NOP();
		}
    }
    if (HAL_DMA_ConfigChannelAttributes(&LcdDmaHandle, DMA_CHANNEL_NPRIV) != HAL_OK)
    {
		for(;;){
			__NOP();
		}
    }
    __HAL_LINKDMA(&SpiHandle,hdmatx,LcdDmaHandle);
	
	/* DMA interrupt init */
	/* SPILCD_DMA_IRQn interrupt configuration */
	HAL_NVIC_SetPriority(SPILCD_DMA_IRQn, 0, 0);
	HAL_NVIC_EnableIRQ(SPILCD_DMA_IRQn);
#endifまた下駄基板ではST7789V2を使用したTFT-LCDモジュールを採用して
おりますがこちらのデータ線はSDIとSDOがマルチプレクスされたSDA
となっており、ST7789V2のデバイスIDを取得したいならばSTM32L5側で
SPIのMOSIとMISOを直結し読み出しの際にMISOの信号を正しく受け取る
MOSIをGPIOの入力にわざわざ切り替えてやる必要があります。
以下にそのコードを示します。
void Display_ChangeSDA_If(uint8_t sda_mode)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	if(sda_mode == TFT_SDA_READ){
		/* Enable CTRL Line GPIO Settings */
		DISPLAY_GPIOCLK_EN(DISPLAY_CLK_SDI);
		GPIO_InitStructure.Pin			= CTRL_SDI;
		GPIO_InitStructure.Mode 		= GPIO_MODE_INPUT;
		GPIO_InitStructure.Pull 		= GPIO_PULLUP;
		GPIO_InitStructure.Speed 		= GPIO_SPEED_FREQ_VERY_HIGH;
		GPIO_InitStructure.Alternate 	= 0;
		HAL_GPIO_Init(DISPLAY_PORT_SDI, &GPIO_InitStructure);
	}
	else {
		/* Enable CTRL Line GPIO Settings */
	#if defined(USE_SOFTWARE_SPI)
		DISPLAY_GPIOCLK_EN(DISPLAY_CLK_SDI);
		GPIO_InitStructure.Pin			= CTRL_SDI;
		GPIO_InitStructure.Mode 		= GPIO_MODE_OUTPUT_PP;
		GPIO_InitStructure.Pull 		= GPIO_NOPULL;
		GPIO_InitStructure.Speed 		= GPIO_SPEED_FREQ_VERY_HIGH;
		GPIO_InitStructure.Alternate 	= 0;
		HAL_GPIO_Init(DISPLAY_PORT_SDI, &GPIO_InitStructure);
	#else
		/* Connect SPI pins to Alternate Function */
		/* Restore SPI MOSI pin configuration */
		DISPLAY_GPIOCLK_EN(DISPLAY_CLK_SDI);
		DISPLAY_PERIF_CLK(ENABLE);
		GPIO_InitStructure.Pin			= CTRL_SDI;
		GPIO_InitStructure.Mode 		= GPIO_MODE_AF_PP;
		GPIO_InitStructure.Pull 		= GPIO_NOPULL;
		GPIO_InitStructure.Speed 		= GPIO_SPEED_FREQ_HIGH;
		GPIO_InitStructure.Alternate 	= SRC_SDI;
		HAL_GPIO_Init(DISPLAY_PORT_SDI, &GPIO_InitStructure);
	#endif
	}
}

ちなみにST7789V2側のドライバはデフォルトでは上記の切り替えの
必要なくIDを決め打ちで返すようにしてますのでもの好きな方だけ
SDAマルチプレクス有効にして試してみてください。
SDAマルチプレクスの際はSTM32側のMOSIとMISOをショートしてください。


ST7789V2からIDを読み出す設定でビルドしてデバッガで追っかけてみると
こんな感じにSDAからST7789V2のID(RDID2(0xDB)で0x85が返る)が
読まれてくるのがわかります。
SPI接続で動くモジュールはこんな感じでピン数節約のためにSDIとSDOが
マルチプレクスされてることもあるので覚えておいて損はないでしょう。

というわけでいつものChaN師のファイラー起動からの…

海で働いてるいないさんのpng形式のイラスツをlibpngでデコード!
(LCDのサイズ小さいので画像の一部しか表示できませんが)
libpngのほかにbmp形式はもちろんlibjpegやgiflibでjpg、gif形式
ファイルも表示できますがSTM32L5シリーズはフラッシュメモリ容量が
512kByteしかないのでフォントファイルを乗せつつ画像デコード用の
ライブラリ全部乗せは容量上非常に苦しいです。
そんなときのために容量を食うフォントファイルは外付けのSPI-ROM
にデータを配置してアクセスしたいところですが…
こういう用途に便利なOCTO-SPIという機能がありますが解説が長く
なりそうなので次回に続きます…!
  
   - 免責・連絡先は↑のリンクを 
 
 ↓SNSもやってます↓
 
  powered by まめわざ powered by まめわざ  - ARM/STM32 (119)
- OpenOCD (27)
- ARM/NxP (34)
- ARM/Cypress (5)
- ARM/Others (3)
- ARM/Raspi (1)
- AVR (13)
- FPGA (4)
- GPS/GNSS (20)
- MISC (86)
- SDCard_Rumors (1)
- STM8 (2)
- Wirelessなアレ (16)
- おきぱ (1)
- ブラウザベンチマーク (29)
- 日本の自然歩道 (27)
   - GNSSモジュールを試用する21 -SAM-M10Qが壊れた…!?と思ったら直せた(おまけあり)-
 ⇒ Kenji Arai (05/29)
- GNSSモジュールを試用する21 -SAM-M10Qが壊れた…!?と思ったら直せた(おまけあり)-
 ⇒ ねむい (05/26)
- GNSSモジュールを試用する21 -SAM-M10Qが壊れた…!?と思ったら直せた(おまけあり)-
 ⇒ Kenji Arai (05/24)
- 中部北陸自然歩道を往く -砺波平野の県境を駆け抜ける!-
 ⇒ ねむい (12/18)
- 中部北陸自然歩道を往く -砺波平野の県境を駆け抜ける!-
 ⇒ ひかわ (12/15)
- STM32U0はぢめました
 ⇒ ねむい (08/07)
- STM32U0はぢめました
 ⇒ ひかわ (07/28)
- STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
 ⇒ ねむい (05/17)
- STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
 ⇒ どじょりん (05/16)
- STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-
 ⇒ どじょりん (05/16)
   - October 2025 (1)
- September 2025 (1)
- August 2025 (1)
- July 2025 (1)
- June 2025 (1)
- May 2025 (1)
- April 2025 (1)
- March 2025 (1)
- February 2025 (1)
- January 2025 (1)
- December 2024 (2)
- November 2024 (1)
- 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.




Comments
Post a Comment