STM 32学習ノート9——stm 32 L 072 SDカードプログラム移植記録

6672 ワード

プロジェクトは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モジュールをマスクします.次のようになります.
#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