STM 32学習ノート9——stm 32 L 072 SDカードプログラム移植記録
プロジェクトはstm 32 L 072を使用し、サンプリングしたデータをSDカードに保存する必要があります.SDカードプログラム参考ST社の公式STM 32 L 073 Z_EVAL開発ボードのルーチン.修正すべき点は以下の通りである:1、stm 32 L 073 z_を修正するeval.hにおけるSPIのピン配置、AF配置;2、公式開発ボードはSTM 32 L 152 CCT 6を使用してSTM 32 L 073のIOポートを拡張し、I 2 Cインタフェースで接続する.SDカードルーチンでは、拡張IOポートは、SDカードが接続されているかどうかを検出するために使用される.我々のボードにはSDカードのハードウェア検出機能が設計されていないのでstm 32 L 073 z_eval_sd.cのBSP_SD_Init関数では、SDカードdetectに関するコードをマスクし、呼び出しSD_のみを保持します.IO_Init関数とreturn.3、stm 320 L 0 xx_hal_conf.hでは、FLASHモジュールを開き、I 2 Cモジュールをマスクします.次のようになります.
4、stm 32 l 073 z_eval.cのSDカード部分には次の文があります.
開発ボードのSDカード部分にはSPIとI 2 Cモジュールが併用されていますが、我々のボードではI 2 Cは使用されていませんので、上記の文のI 2 Cをマスクします.
これで、ソースファイルの基本的な変更が完了し、プログラムを実行できます.しかしmain関数では呼び出し関数f_が発見されたmkfs((TCHAR const*)SDPath, 0, 0);時にFR_に戻るDISK_ERRエラー.単一ステップデバッグでファイルdickioでエラーが発生しました.cの関数disk_write、この関数の定義は以下の通りです.
これはちょっと乱れていますが、形式的には関数disk_writeは自分を呼び出した!この関数はどのように最下位のSPI書き込み関数を呼び出して、工事の中でどのようにdisk_を検索しますwriteは見つかりませんでした.単一ステップのデバッグを続行すると、stm 32 l 073 zにジャンプしました.eval_sd.cファイルのSD_write関数.とりあえずどうやってSDを呼び出してもwrite関数は、まずなぜ間違っているのかを探しましょう.ワンステップデバッグを続け、SD_を発見write呼び出しBSP_SD_WriteBlocks、BSP_SD_WriteBlocksでエラーが発生したのは、次の文です.
ああ、メモリを動的に割り当てるときにエラーが発生しました.sizeof(uint 8_t)*BlockSizeのサイズを512としてテストし、上記の文を直接次のように変更してみます.
もう間違いを報告しない.これで、問題が明らかになりました.大きなスペースを動的に割り当てるとエラーが発生し、エラーが発生するのはスタック設定が小さいためです.起動ファイル(.s)で文を
に改心
もう一度テストして、プログラムは合格しました.プログラムを記録し、正常に実行します.
最後に、もう一つ残った問題があります.関数disk_writeはどのように関数SD_を呼び出しますwriteのは?disk_を検索する以上writeで結果が見つからなかったらSD_を検索writeやってみます.やっぱり、sd_diskio.cでは、以下の定義が見つかった.
構造体Diskio_drvType Defの定義は次のとおりです.
これで、SD_Driverは構造体で、SD_を指す関数ポインタDRESULT(*disk_write)が入っています.write関数.どうやら、SD_write関数はSD_Driverが呼び出しました.SD_の検索Driverは、main関数の最初に次の文があることを発見しました.
この関数を研究すると、関数SD_が発見されます.writeはこのlink関数を介してグローバル変数diskに接続され、関数disk_writeで呼び出します.(関数disk_writeをもう一度貼り付けます)
関数disk_writeで呼び出されたdisk_writeは関数disk_ではありませんwrite自体!構造体diskである.drvにおける関数ポインタであり、このポインタは関数SD_を指すwrite関数.2つのdisk_writeの名前が同じなので、誤解を引き起こしました.O( ̄) ̄)o
#define HAL_FLASH_MODULE_ENABLED
#define HAL_GPIO_MODULE_ENABLED
/* #define HAL_I2C_MODULE_ENABLED */
4、stm 32 l 073 z_eval.cのSDカード部分には次の文があります.
#if defined(HAL_SPI_MODULE_ENABLED) && defined(HAL_I2C_MODULE_ENABLED)
開発ボードのSDカード部分にはSPIとI 2 Cモジュールが併用されていますが、我々のボードではI 2 Cは使用されていませんので、上記の文のI 2 Cをマスクします.
#if defined(HAL_SPI_MODULE_ENABLED) //&& defined(HAL_I2C_MODULE_ENABLED)
これで、ソースファイルの基本的な変更が完了し、プログラムを実行できます.しかしmain関数では呼び出し関数f_が発見されたmkfs((TCHAR const*)SDPath, 0, 0);時にFR_に戻るDISK_ERRエラー.単一ステップデバッグでファイルdickioでエラーが発生しました.cの関数disk_write、この関数の定義は以下の通りです.
#if _USE_WRITE == 1
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
return res;
}
これはちょっと乱れていますが、形式的には関数disk_writeは自分を呼び出した!この関数はどのように最下位のSPI書き込み関数を呼び出して、工事の中でどのようにdisk_を検索しますwriteは見つかりませんでした.単一ステップのデバッグを続行すると、stm 32 l 073 zにジャンプしました.eval_sd.cファイルのSD_write関数.とりあえずどうやってSDを呼び出してもwrite関数は、まずなぜ間違っているのかを探しましょう.ワンステップデバッグを続け、SD_を発見write呼び出しBSP_SD_WriteBlocks、BSP_SD_WriteBlocksでエラーが発生したのは、次の文です.
ptr = malloc(sizeof(uint8_t)*BlockSize);
ああ、メモリを動的に割り当てるときにエラーが発生しました.sizeof(uint 8_t)*BlockSizeのサイズを512としてテストし、上記の文を直接次のように変更してみます.
ptr = malloc(256);
もう間違いを報告しない.これで、問題が明らかになりました.大きなスペースを動的に割り当てるとエラーが発生し、エラーが発生するのはスタック設定が小さいためです.起動ファイル(.s)で文を
Heap_Size EQU 0x00000200
に改心
Heap_Size EQU 0x00000400
もう一度テストして、プログラムは合格しました.プログラムを記録し、正常に実行します.
最後に、もう一つ残った問題があります.関数disk_writeはどのように関数SD_を呼び出しますwriteのは?disk_を検索する以上writeで結果が見つからなかったらSD_を検索writeやってみます.やっぱり、sd_diskio.cでは、以下の定義が見つかった.
const Diskio_drvTypeDef SD_Driver =
{
SD_initialize,
SD_status,
SD_read,
#if _USE_WRITE == 1
SD_write,
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
SD_ioctl,
#endif /* _USE_IOCTL == 1 */
};
構造体Diskio_drvType Defの定義は次のとおりです.
/**
* @brief Disk IO Driver structure definition
*/
typedef struct
{
DSTATUS (*disk_initialize) (BYTE); /*!< Initialize Disk Drive */
DSTATUS (*disk_status) (BYTE); /*!< Get Disk Status */
DRESULT (*disk_read) (BYTE, BYTE*, DWORD, UINT); /*!< Read Sector(s) */
#if _USE_WRITE == 1
DRESULT (*disk_write) (BYTE, const BYTE*, DWORD, UINT); /*!< Write Sector(s) when _USE_WRITE = 0 */
#endif /* _USE_WRITE == 1 */
#if _USE_IOCTL == 1
DRESULT (*disk_ioctl) (BYTE, BYTE, void*); /*!< I/O control operation when _USE_IOCTL = 1 */
#endif /* _USE_IOCTL == 1 */
}Diskio_drvTypeDef;
これで、SD_Driverは構造体で、SD_を指す関数ポインタDRESULT(*disk_write)が入っています.write関数.どうやら、SD_write関数はSD_Driverが呼び出しました.SD_の検索Driverは、main関数の最初に次の文があることを発見しました.
FATFS_LinkDriver( &SD_Driver, SDPath ) == 0
この関数を研究すると、関数SD_が発見されます.writeはこのlink関数を介してグローバル変数diskに接続され、関数disk_writeで呼び出します.(関数disk_writeをもう一度貼り付けます)
DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
DRESULT res;
res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
return res;
}
関数disk_writeで呼び出されたdisk_writeは関数disk_ではありませんwrite自体!構造体diskである.drvにおける関数ポインタであり、このポインタは関数SD_を指すwrite関数.2つのdisk_writeの名前が同じなので、誤解を引き起こしました.O( ̄) ̄)o