STM32H5を使ってみる6 -秋月販売記念!SDMMCとFatFsでSDカードを使う-

秋月さんからついにNUCLEO-H563ZIが販売となりました!!!
これで皆様も気軽にSTM32H5をいじることができるでしょう〜!

ちなみにSTM32H5に対応したOpenOCDはねむいさんのぶろぐで公開
しておりますので
どしどしご利用ください!!!!
そうだね宣伝だね!!

あ、それと買った人チップリビジョンちゃんと確認してくださいね…
Zならはずれです…


●STM32H5のSDMMC
そんなわけで今回はSTM32H5のSDMMC機能を利用してFatFsを移植し
SDカードやMMC/eMMCからデータの読み書きを行うところまでを
紹介します。


STM32H5のSDMMCにはSTM32H7と同じくIDMAというGPDMAから独立した
DMAが存在しており、GPDMAと干渉することなく運用が可能です。


また、STM32H5は外部メモリ(FSMC/OCTO-SPI)にしかDキャッシュが
かかわってこないためキャッシュコントロールの面倒さもありません。

●STM32H5では公式にFatFsの移植例がないが…
STM32H5以降はMicrosoft Azure RTOSに入れ込んでおりFatFsではなく
FILEXなるソフトウエアライブラリに置き変わっておりました。

ねむいさんは慣れ親しんだFatFs以外の選択肢はないのでFILEXはガン
無視のザ・シカトで移植に挑みました。


移植についてですがSTM32F7のころから慣れ親しんだいわば"枯れた"
ペリフェラルなのでHALの構造も酷似しているためSTM32H7やSTM32L5の
移植例からI/Oとクロック設定以外はほぼスライド移植で簡単にできて
しまいました!

f_readの結合関数SD_read()はこんな感じです。

DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
DRESULT res = RES_OK;
uint32_t timer = SysTick->VAL + SD_DATATIMEOUT;

/* first ensure the SDCard is ready for a new operation */
while((SD_GetCardState() == SD_TRANSFER_BUSY))
{
if(timer < SysTick->VAL)
return RES_NOTRDY;
}

#if defined(SD_DMA_MODE) && !defined(SD_POLLING_MODE)

if((uintptr_t)buff & 0x3) /* Check 4Byte Alignment */
{ /* Unaligned Buffer Address Case (Slower) */
for (unsigned int secNum = 0; secNum < count ; secNum++){

if(SD_ReadBlocks_DMA((uint32_t*)dmabuf, (uint32_t)(sector+secNum), 1)!= MSD_OK)
{
MSG_PRINTF("Read error on unaligned buffer¥n");
res = RES_ERROR;
}

memcpy(buff+secNum*SECTOR_SIZE, dmabuf, SECTOR_SIZE);
}
} else {
/* Aligned Buffer Address Case (Faster) */
if(SD_ReadBlocks_DMA((uint32_t*)buff, (uint32_t)sector, count) != MSD_OK)
{
MSG_PRINTF("Read error on DMA¥n");
res = RES_ERROR;
}
}
#else
if(SD_ReadBlocks((uint32_t*)buff, (uint32_t)sector, count) != MSD_OK)
{
MSG_PRINTF("Read error on polling¥n");
res = RES_ERROR;
}
#endif
return res;
}


f_writeの結合関数SD_write()はこんな感じです。
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
DRESULT res = RES_ERROR;
uint32_t timer;


#if defined(SD_DMA_MODE) && !defined(SD_POLLING_MODE)
if((uintptr_t)buff & 0x3) /* Check 4Byte Alignment */
{ /* Unaligned Buffer Address Case (Slower) */
for (unsigned int secNum = 0; secNum < count; secNum++){

memcpy(dmabuf, buff+(SECTOR_SIZE*secNum), SECTOR_SIZE);

if(SD_WriteBlocks_DMA((uint32_t*)dmabuf, (uint32_t)(sector+secNum), 1) != MSD_OK)
{
MSG_PRINTF("Write error on unaligned buffer¥n");
res = RES_ERROR;
}
}
} else {
if(SD_WriteBlocks_DMA((uint32_t*)buff, (uint32_t)sector, count) != MSD_OK)
{
MSG_PRINTF("Write error on DMA¥n");
res = RES_ERROR;
}
}
#else
if(SD_WriteBlocks((uint32_t*)buff, (uint32_t)sector, count) != MSD_OK)
{
MSG_PRINTF("Write error on polling¥n");
res = RES_ERROR;
}

#endif

/* ensure the SDCard is ready for a next operation */
timer = SysTick->VAL + SD_DATATIMEOUT;
res = RES_ERROR; /* Timeout */
/* block until SDIO IP is ready or a timeout occur */
while(timer > SysTick->VAL)
{
if(SD_GetCardState() == SD_TRANSFER_OK)
{
res = RES_OK;
break;
}
}

return res;
}

キャッシュコントロールがないのですっきりですね。
全体的なソースの詳細についてはねむいさんのSTM32H5プロジェクト内の
下記ディレクトリのファイルを参照してください。
./lib/ff/sdmmc_stm32h5.c
./lib/ff/sdmmc_stm32h5.h


●直線リードのパフォーマンスはどんな感じか

STM32H5の最大クロックは250MHz取れるのでSDMMCのクロック周波数も
250/5=50MHzとハイスピードの規格いっぱいの50MHzでぶん回すことが
可能です。

直線の読み出しスピードは19MBytes/Sec出てますね。
こんだけあれば十分でしょう。


ちなみにeMMCでは3.3VでDDRモードに対応しており、STM32H5のSDMMCも
DDRに対応しているのでSDカードを超えた早い読み出しが可能です!!

●SMART取得機能も搭載

ねむいさんはSMARTが取れる産業用/工業用SDカードが大好きですが
STM32H5でももちろんSMARTの取得を可能としてます!
試される際は上記のコードをコメントアウトしてくださいね〜

SMART対応のSDカードについては下記記事もご参照ください!
DELKIN製SDカード
TRANSCEND製microSDカード



そんなわけでかなりやっけつ気味にSTM32H5へのSDMMCを使ったFatFs
の移植を紹介しましたがそれらを組み込んだ総合的な成果物は昨年
からすでにおきぱで公開しておりますので
どしどし参考にしてください!

Comments

Post a Comment








Go to top of page