STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项,以及配置4bit模式可能出现卡死问题的解决方法

一、使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项:

以STM32F429为例:
1、SDIO配置
在这里插入图片描述
配置为4bit模式,此配置不是最终配置,后面会在代码进行修改。
2、Fatfs配置
在这里插入图片描述
Set Defines 选项中的配置可以默认,最重要注意Advanced Setting 选择中的配置,如下
在这里插入图片描述
该界面配置默认Use dma template是默认使能的 ,并且不可以选择,只能选择使能,所以需要使能 SDIO中断和SDIO DMA(注意:如果不使能可能会出现问题),如下图所示:
在这里插入图片描述
在这里插入图片描述
在使能中断之后,注意 SDIO global 中断要小于或者等于SDIO DMA的中断,否则会出现问题
3、FreeRTOS配置
FreeRTOS配置默认即可
在这里插入图片描述
配置完成记得把启动文件的堆栈改大一点,如下:
在这里插入图片描述
生成代码即可

二、生成代码修改:

找到sdio.c文件中的void MX_SDIO_SD_Init(void)函数,修改如下:

void MX_SDIO_SD_Init(void)
{

  /* USER CODE BEGIN SDIO_Init 0 */

  /* USER CODE END SDIO_Init 0 */

  /* USER CODE BEGIN SDIO_Init 1 */

  /* USER CODE END SDIO_Init 1 */
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_4B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 4;
  /* USER CODE BEGIN SDIO_Init 2 */
	//初始化时使用1bit + SDIO_INIT_CLK_DIV初始化时钟频率
	hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
	hsd.Init.ClockDiv = SDIO_INIT_CLK_DIV;//SDIO_TRANSFER_CLK_DIV;
  /* USER CODE END SDIO_Init 2 */

}

在这里插入图片描述
经过实际测试,使用最大频率也是可以的,但是初始化时使用1bit+SDIO_INIT_CLK_DIV 初始化时钟频率,防止不必要的错误

在生成的bsp_driver_sd.c文件中找到__weak uint8_t BSP_SD_Init(void)函数,该函数是一个弱函数,可在其他文件复写,如下:

uint8_t BSP_SD_Init(void)
{
  uint8_t sd_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR;
  }
  /* HAL SD initialization */
  sd_state = HAL_SD_Init(&hsd);
  
  /* Configure SD Bus width (4 bits mode selected) */
  if (sd_state == MSD_OK)
  {
	hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;//改为最大传输频率
    /* Enable wide operation */
    if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    {
      sd_state = MSD_ERROR;
    }
  }

  return sd_state;
}

由于使用的SD卡支持改频率,所以我采用SDIO_TRANSFER_CLK_DIV最大频率,这里分频根据不同的SD卡可做调整。
在这里插入图片描述
我这里是在main.c复写的,到这一步可能会出现HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)函数卡死的问题,如果遇到该问题此时我们需要重写几个函数如下:

static uint32_t My_SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
{
  SDIO_DataInitTypeDef config;
  uint32_t errorstate;
  uint32_t tickstart = HAL_GetTick();
  uint32_t index = 0U;
  uint32_t tempscr[2U] = {0U, 0U};
  uint32_t *scr = pSCR;
	uint16_t delay_time;
  /* Set Block Size To 8 Bytes */
  errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  /* Send CMD55 APP_CMD with argument as card's RCA */
  errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U));
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  config.DataTimeOut   = SDMMC_DATATIMEOUT;
  config.DataLength    = 8U;
  config.DataBlockSize = SDIO_DATABLOCK_SIZE_8B;
  config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
  config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
  config.DPSM          = SDIO_DPSM_ENABLE;
  (void)SDIO_ConfigData(hsd->Instance, &config);

  //添加延时,等待处琿
  for(delay_time = 0; delay_time < 20; delay_time++)
  {
	__nop();
  }
  
  /* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
  errorstate = SDMMC_CmdSendSCR(hsd->Instance);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT))
  {
    if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL))
    {
      *(tempscr + index) = SDIO_ReadFIFO(hsd->Instance);
		index++;
		if (index == 2)
			break;//因为定义index的时候初始忼是0,但是你们自己追踪下,事实上发鿁这条命令只会返回两个数据, 我的返回的是两个0.而返回两个数据后基本总线就没反映了,成了死循玿
    }
    else if(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXACT))
    {
      break;
    }

    if((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
    {
      return HAL_SD_ERROR_TIMEOUT;
    }
  }

  if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT))
  {
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DTIMEOUT);

    return HAL_SD_ERROR_DATA_TIMEOUT;
  }
  else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
  {
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DCRCFAIL);

    return HAL_SD_ERROR_DATA_CRC_FAIL;
  }
  else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
  {
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_RXOVERR);

    return HAL_SD_ERROR_RX_OVERRUN;
  }
  else
  {
    /* No error flag set */
    /* Clear all the static flags */
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);

    *scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24)  | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\
            ((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24));
    scr++;
    *scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24)  | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\
            ((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24));

  }

  return HAL_SD_ERROR_NONE;
}

static uint32_t My_SD_WideBus_Enable(SD_HandleTypeDef *hsd)
{
  uint32_t scr[2U] = {0U, 0U};
  uint32_t errorstate;

  if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
  {
    return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
  }

  /* Get SCR Register */
  errorstate = My_SD_FindSCR(hsd, scr);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  /* If requested card supports wide bus operation */
  if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
  {
    /* Send CMD55 APP_CMD with argument as card's RCA.*/
    errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
    errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    return HAL_SD_ERROR_NONE;
  }
  else
  {
    return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
  }
}

static uint32_t My_SD_WideBus_Disable(SD_HandleTypeDef *hsd)
{
  uint32_t scr[2U] = {0U, 0U};
  uint32_t errorstate;

  if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
  {
    return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
  }

  /* Get SCR Register */
  errorstate = My_SD_FindSCR(hsd, scr);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    return errorstate;
  }

  /* If requested card supports 1 bit mode operation */
  if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO)
  {
    /* Send CMD55 APP_CMD with argument as card's RCA */
    errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    /* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
    errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U);
    if(errorstate != HAL_SD_ERROR_NONE)
    {
      return errorstate;
    }

    return HAL_SD_ERROR_NONE;
  }
  else
  {
    return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
  }
}

HAL_StatusTypeDef My_HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)
{
  SDIO_InitTypeDef Init;
  uint32_t errorstate;
  HAL_StatusTypeDef status = HAL_OK;

  /* Check the parameters */
  assert_param(IS_SDIO_BUS_WIDE(WideMode));

  /* Change State */
  hsd->State = HAL_SD_STATE_BUSY;

  if(hsd->SdCard.CardType != CARD_SECURED)
  {
    if(WideMode == SDIO_BUS_WIDE_8B)
    {
      hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
    }
    else if(WideMode == SDIO_BUS_WIDE_4B)
    {
      errorstate = My_SD_WideBus_Enable(hsd);

      hsd->ErrorCode |= errorstate;
    }
    else if(WideMode == SDIO_BUS_WIDE_1B)
    {
      errorstate = My_SD_WideBus_Disable(hsd);

      hsd->ErrorCode |= errorstate;
    }
    else
    {
      /* WideMode is not a valid argument*/
      hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
    }
  }
  else
  {
    /* MMC Card does not support this feature */
    hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
  }

  if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
  {
    /* Clear all the static flags */
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
    hsd->State = HAL_SD_STATE_READY;
    status = HAL_ERROR;
  }
  else
  {
    /* Configure the SDIO peripheral */
    Init.ClockEdge           = hsd->Init.ClockEdge;
    Init.ClockBypass         = hsd->Init.ClockBypass;
    Init.ClockPowerSave      = hsd->Init.ClockPowerSave;
    Init.BusWide             = WideMode;
    Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;
    Init.ClockDiv            = hsd->Init.ClockDiv;
    (void)SDIO_Init(hsd->Instance, Init);
  }

  /* Set Block Size for Card */
  errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
  if(errorstate != HAL_SD_ERROR_NONE)
  {
    /* Clear all the static flags */
    __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
    hsd->ErrorCode |= errorstate;
    status = HAL_ERROR;
  }

  /* Change State */
  hsd->State = HAL_SD_STATE_READY;

  return status;
}

uint8_t BSP_SD_Init(void)
{
	
	uint8_t sd_state = MSD_OK;
	/* Check if the SD card is plugged in the slot */
	if (BSP_SD_IsDetected() != SD_PRESENT)
	{
		return MSD_ERROR;
	}
	/* HAL SD initialization */
	sd_state = HAL_SD_Init(&hsd);
	/* Configure SD Bus width (4 bits mode selected) */
	if (sd_state == MSD_OK)
	{
		hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;//
		/* Enable wide operation */
		if (My_HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
		{
			sd_state = MSD_ERROR;
		}
	}
	return sd_state;
}

此时,卡死问题就会解决。

进行实际读写测试:
在这里插入图片描述
调试发现能够正常读写,本次分享到此结束。

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
DSP和标准外设库: 资源编号 : STSW-STM32065 资源名称 : STM32F4 DSP and standard peripherals library 文件名 : stm32_f105-07_f2_f4_usb-host-device_lib.zip 下载地址 : http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257901# USB库: 资源编号 : STSW-STM32046 资源名称 : STM32F105/7, STM32F2 and STM32F4 USB on-the-go Host and device library (UM1021) 文件名 : stm32_f105-07_f2_f4_usb-host-device_lib.zip 下载地址 : http://www.st.com/web/en/catalog/tools/PF257882 ETH以太网库: 资源编号 : STSW-STM32046 资源名称 : LwIP TCP/IP stack demonstration for STM32F4x7 microcontrollers (AN3966) 文件名 : stsw-stm32070.zip 下载地址 : http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257906 【CMSIS】 Cortex微控制器软件接口程序(Cortex Microcontroller Software Interface Standard (CMSIS). ) 版本: V4.2 发布日期: 31. July 2014 【STM32F4xx_StdPeriph_Driver】 STM32F40x系列CPU标准外设驱动程序 版本: V1.5.0 发布日期: 06-March-2015 【STM32_USB_OTG_Driver】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Device Library 版本: V2.1.0 发布日期: 2012-03-19 【STM32_USB_Device_Library】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Device Library 版本: V1.1.0 发布日期: 2012-03-05 【STM32_USB_HOST_Library】 STM32F105/7xx, STM32F2xx and STM32F4xx USB Host Library 版本: V2.1.0 发布日期: 2012-03-19 【STM32F4x7_ETH_Driver】 STM32F4x7 Eth Library 版本: V1.1.0 发布日期: 31-July-2013 ********************************************************************************************************* * * 版 本 : V1.0 * 说 明 : 本实验主要实现FreeRTOS+STemWin+FatFS+USB Host综合 * 实验目的: * 1. 学习FreeRTOS+STemWin+FatFS+USB Host综合 * 2. 这里的USB Host主要实现U盘相关处理,支持U盘热插拔。 * 用户可以根据需要在usb_usr.c文件中的插入检测函数: * USBH_USR_Configuration_DescAvailable或者函数USBH_USR_Init函数加入插入标志 * 拔出检测函数: * USBH_USR_DeviceDisconnected * 实验内容: * 1. 按下按键K1可以通过串口打印任务执行情况(波特率115200,数据位8,奇偶校验位无,停止位1) * ================================================= * 任务名 任务状态 优先级 剩余栈 任务序号 * vTaskUserIF R 2 272 2 * vTaskGUI R 1 657 1 * IDLE R 0 113 6 * vTaskMsgPro B 4 1957 4 * vTaskLED B 3 483 3 * vTaskStart B 5 489 5 * * * 任务名 运行计数 使用率 * vTaskUserIF 5583 1% * vTaskGUI 10782 2% * IDLE 355589 91% * vTaskLED 0 <1% * vTaskMsgPro 16770 4% * vTaskStart 17 <1% * 串口软件建议使用SecureCRT(V6光盘里面有此软件)查看打印信息。 * 各个任务实现的功能如下: * vTaskGUI 任务: emWin任务 * vTaskTaskUserIF 任务: 接口消息处理 * vTaskLED 任务: LED闪烁 * vTaskMsgPro 任务: U盘中文件处理和浏览 * vTaskStart 任务: 启动任务,也就是最高优先级任务,这里实现按键扫描和触摸检测 * 2. 任务运行状态的定义如下,跟上面串口打印字母B, R, D, S对应: * #define tskBLOCKED_CHAR ( 'B' ) 阻塞 * #define tskREADY_CHAR ( 'R' ) 就绪 * #define tskDELETED_CHAR ( 'D' ) 删除 * #define tskSUSPENDED_CHAR ( 'S' ) 挂起 * 3. 本实验的USB Host主要是对U盘的操作,通过电脑端的串口软件SecureCRT软件, * 给板子发送相关命令实现操作,具体实现在demo_fatfs文件里面。 * printf("请选择操作命令:\r\n"); * printf("1 - 显示根目录下的文件列表\r\n"); * printf("2 - 创建一个新文件armfly.txt\r\n"); * printf("3 - 读armfly.txt文件的内容\r\n"); * printf("4 - 创建目录\r\n"); * printf("5 - 删除文件和目录\r\n"); * printf("6 - 读写文件速度测试\r\n"); * printf("7 - 挂载U盘\r\n"); * printf("8 - 卸载U盘\r\n"); * 注意事项: * 1. 本实验推荐使用串口软件SecureCRT,要不串口打印效果不整齐。此软件在 * V5开发板光盘里面有。 * 2. 务必将编辑器的缩进参数和TAB设置为4来阅读本文件,要不代码显示不整齐。 * * 修改记录 : * 版本号 日期 作者 说明 * V1.0 2016-03-15 Eric2013 1. ST固件库到V1.5.0版本 * 2. BSP驱动包V1.2 * 3. FreeRTOS版本V8.2.3 * 4. STemWin版本V5.28 * 5. FatFS版本V0.11a * * Copyright (C), 2016-2020, 安富莱电子 www.armfly.com * *********************************************************************************************************

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值