STM32CubeMx + SD Card + FatFs 读写SD卡死等问题

Cube Mx使用较新版本 Version:4.24.0

MDK v5.20

STM32F429ZGT6

两年以前记得试过SD卡读写,好像不是单纯的Read和Write,应该是用了文件系统,很顺利的试验成功了,所以源码和记录都没留,这次要做一个新的板子,真所谓苦难重重啊,到现在32.768K的晶振一直没起振,由原来的10P电容换了6P的,还是不行,应该说偶尔可以,但生产代码中MX_RTC_Init() 依然死在里面,LSE未就绪啊~, 言归正传,写了一个试验SD卡的程序,f_open 死在路上了,经调试发现ReadStatus 始终不会置1,唯一修改其值的方法BSP_SD_ReadCpltCallback根本没人调用,先是怀疑自己配置,在方法SD_read中直接调用了BSP_SD_ReadBlocks_DMA,可见,不用DMA不行,配置SDIO的DMA,如下

STM32CubeMx + SD Card + FatFs 读写SD卡死等问题_第1张图片

通过调试,还是不行,现在的中断函数已经被调用了HAL_DMA_IRQHandler,中断方法中传输完成调用hdma->XferM1CpltCallback(hdma); 而在读取方法中设置回调 hsd->hdmarx->XferCpltCallback = SD_DMAReceiveCplt; 在SD_DMAReceiveCplt方法中最后调用了HAL的回调HAL_SD_RxCpltCallback(hsd);而此方法又空,和希望的回调基本同名BSP_SD_ReadCpltCallback。所以把读写都放到此方法里(文件stm32f4xx_hal_sd.c 头加入extern void BSP_SD_ReadCpltCallback(void); extern void BSP_SD_WriteCpltCallback(void);)至此,Open方法过去了,但写方法一直失败,原因是HAL_SD_TxCpltCallback居然没地方调用,放到方法SD_DMATransmitCplt里,写一次后返回HAL_OK,但hsd->State一直是busy,导致下次读直接返回HAL_ERROR,再次在方法SD_DMATransmitCplt中添加hsd->State = HAL_SD_STATE_READY;至此SD卡读写正常。

总结一下生成代码后的改动:

stm32f4xx_hal_sd.c

 //dp:add at2018.6.20
extern void BSP_SD_ReadCpltCallback(void);
extern void BSP_SD_WriteCpltCallback(void);
/**
  * @brief Tx Transfer completed callbacks
  * @param hsd Pointer to SD handle
  * @retval None
  */
 __weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(hsd);
    //dp:add
    BSP_SD_WriteCpltCallback();
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_SD_TxCpltCallback can be implemented in the user file
   */
}

/**
  * @brief Rx Transfer completed callbacks
  * @param hsd Pointer SD handle
  * @retval None
  */
__weak void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(hsd);
    //dp:add
    BSP_SD_ReadCpltCallback();
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_SD_RxCpltCallback can be implemented in the user file
   */
}
/**
  * @brief  DMA SD transmit process complete callback 
  * @param  hdma DMA handle
  * @retval None
  */
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)     
{
  SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
  
  /* Enable DATAEND Interrupt */
  __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND));
    //dp:add
    hsd->State = HAL_SD_STATE_READY;
    HAL_SD_TxCpltCallback(hsd);
}
例子程序:试了一下128的数组没问题,然后写到外扩SRAM里,再写入SD卡,再读128也没问题,最后的长度判断请忽略
/**
  ******************************************************************************
  * @file    xx_module_debug.c
  * @author  deep
  * @version V1.0.0
  * @date    2018.6.14
  * @brief   debug module
  ******************************************************************************
  */

#include "main.h"
#include "ff.h"
#include "string.h"
#include "xx_base_types.h"

U32 m_sram_addr = 0x64000000;
void xx_fill_sram(void);

FATFS fs;
FIL fil;

char sd_file_name[] = "hd_sd_test.txt";

extern void _Error_Handler(char *file, int line);
extern uint8_t retSD;

void hd_sd_file_read_write(void)
{
    //char szwrite[128];
    char szread[128];
    U32 bytewritten;
    U32 byteread;
    U32 ADD = m_sram_addr;
    
    if (retSD != 0)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    hd_fill_sram();
    
    retSD = f_mount(&fs, "", 0);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    retSD = f_open(&fil, sd_file_name, FA_CREATE_ALWAYS | FA_WRITE);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    //strcpy(szwrite, " This function is called in f_mount() function to create a new !!\n");
    //retSD = f_write(&fil, (void *)szwrite, strlen(szwrite), (void *)&bytewritten);
    retSD = f_write(&fil, (void *)ADD, 512, (void *)&bytewritten);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    retSD = f_write(&fil, (void *)(ADD + 512), 512, (void *)&bytewritten);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    retSD = f_write(&fil, (void *)(ADD + 512), 512, (void *)&bytewritten);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    retSD = f_close(&fil);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    retSD = f_open(&fil, sd_file_name, FA_READ);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    retSD = f_read(&fil, szread, sizeof(szread), (U32 *)&byteread);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    retSD = f_close(&fil);
    if (retSD)
    {
        _Error_Handler(__FILE__, __LINE__);
    }
    
    if (byteread == bytewritten)
    {
        printf("FATFS OK!!!!!!!!!");
    }
    else
    {
        printf("FATFS ERROR, ERROR, ERROR!");
    }
    
}

时钟设置

STM32CubeMx + SD Card + FatFs 读写SD卡死等问题_第2张图片


SDIO设置

STM32CubeMx + SD Card + FatFs 读写SD卡死等问题_第3张图片

STM32CubeMx + SD Card + FatFs 读写SD卡死等问题_第4张图片

单次写操作大于512会出错,暂时没去纠结原因,回头更新了版本再试。

-------------------------------------------------------------------------------------------------------

2018.6.21 发现个很弱的弱函数标示,一直没有注意

__weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)

注:

weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”

加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,

那么编译器就会执行__weak 声明的函数,并且编译器不会报错。

所以最终更改,在文件 sd_diskio.c 中末尾加入:

/* USER CODE BEGIN lastSection */ 
/* can be used to modify / undefine previous code or add new code */
void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
{
    BSP_SD_WriteCpltCallback();
}

void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
{
     BSP_SD_ReadCpltCallback();
}
/* USER CODE END lastSection */
SD_DMATransmitCplt 方法中的添加暂时没找到好办法,防止生成时覆盖。


你可能感兴趣的:(技术类学习)