STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项

这篇具有很好参考价值的文章主要介绍了STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

二、生成代码修改:

找到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 */

}

stm32cubemx配置freertos,stm32,单片机,嵌入式硬件
经过实际测试,使用最大频率也是可以的,但是初始化时使用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卡可做调整。
stm32cubemx配置freertos,stm32,单片机,嵌入式硬件
我这里是在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;
}

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

进行实际读写测试:
stm32cubemx配置freertos,stm32,单片机,嵌入式硬件
调试发现能够正常读写,本次分享到此结束。文章来源地址https://www.toymoban.com/news/detail-676261.html

到了这里,关于STM32使用STM32CUBEMX配置FreeRTOS+SDIO4bit+FATFS注意事项的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32CubeMX教程27 SDIO - 读写SD卡

    正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) ST-LINK/V2驱动 逻辑分析仪nanoDLA 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX软件配置STM32F407开发板 SDIO读写4线SD卡,实现轮询方式读写SD卡、以中断方式读取SD卡和以DMA方式读取SD卡 安全数码

    2024年02月19日
    浏览(63)
  • STM32 CubeMX (第四步Freertos内存管理和CPU使用率)

    学习使用Freertos第四步 在 FreeRTOS 中,中断管理和软件定时: · taskENTER_CRITICAL() ·; 是一个函数在 FreeRTOS 中使用的,用于进入临界区(critical section)。在临界区内,中断会被禁用,这样可以确保在多任务环境下共享资源的安全性。你可以在需要保护共享资源的代码段中使用 ·

    2024年02月12日
    浏览(45)
  • 【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子

    【STM32】HAL库 新建MDK工程 【STM32】HAL库 串口轮询发送 【STM32】HAL库 LED闪烁、流水灯 【STM32】HAL库 定时器中断 【STM32】HAL库 外部中断 使用STM32F103C8T6开发板,用STM32CubeMX配置FreeRTOS,可以适配正点原子FreeRTOS所有实验的基础工程 HAL的时基不能选择系统定时器 PA0和PA1输出模式,

    2024年02月19日
    浏览(50)
  • 【通过STM32CubeMx配置LWIP+FreeRTOS并通过Socket实现TCP_Client/Sever】

    测试平台 → Nucleo_F429ZI 软件工具 → STM32CubeMx 6.6.1 MDK 5.3.0 网络调试助手V1.2 在CubeMx上面选择NUCLEO-F429ZI开发板,并采用默认配置 使能FreeRTOS 修改defaultTask的栈大小 由于使用了FreeRTOS,因此系统的TimeBase Source修改成TIM1 使能LWIP,并且先禁用DHCP,设置好静态IP Platform选择LAN8742 修改

    2024年02月08日
    浏览(43)
  • STM32CubeMX系列09——SDIO(SD卡读写、SD卡移植FATFS文件系统)

    ==== 文章汇总(有代码汇总) ==== 准备看看这方面的知识,一时间还没不清有什么区别,先补补课,不需要的跳过。 参考文章(内容来源):http://www.360doc.com/content/21/1125/22/59057945_1005908465.shtml 主要写这两个:SD卡、TF卡 共同点:SD、TF、MMC都是在MMC基础上演化发展不同的规范,

    2024年02月09日
    浏览(46)
  • STM32 CubeMX LwIP + freertOS 移植

    开发板: 官方 STM32F746  MCU型号:STM32F746NGH 网卡型号:LAN8742A  原理图如下 先用裸机测试LAN8742A的网卡驱动 使用CubeMX创建工程 系统时钟和时基定时器如下 无系统LWIP协议栈设置,静态IP地址,关闭DHCP 生产代码,下载进开发板。开发板网口与电脑网口通过网线直连,设置电脑本

    2024年01月16日
    浏览(83)
  • 基于STM32CubeMX创建FreeRTOS—以STM32F429为例

    目录 1. 实验任务 2. 使用STM32CubeMX创建基础工程 2.1 使用STM32CubeMX创建项目 2.2 创建新项目 2.3 时钟设置 2.4 时钟配置树 2.5 修改时钟基准,打开串行调试 2.6 配置串口 2.7 配置状态指示灯 2.8 FreeRTOS配置 2.9 配置工程输出项 3. 代码编辑 3.1 printf重映射 3.1.1 使用ARMCC 5编译器时的print

    2024年01月22日
    浏览(42)
  • 搭建STM32F407的Freertos系统(基于STM32CubeMX)

           本人长期开发Linux、Windows上应用软件,一直以来MCU开发有所接触,但较少(最近项目需要,小公司么,都得会,被逼的),好在有STM32CubeMX这样工具,貌似就是我想要的工具。         本次demo目标立下:         1. 搭建或移植FreeRTOS到STM32上,毕竟对于长期在Linux环境

    2024年02月10日
    浏览(61)
  • STM32 CubeMX (Freertos任务:创建、删除、挂起、恢复)

    学习使用Freertos第一步 FreeRTOS 任务管理,您需要掌握以下几个关键函数: 1. xTaskCreate() :用于创建一个任务,需要指定任务函数、任务名称、任务栈大小和优先级等参数。 2. vTaskDelete() :用于删除一个任务,可以由任务自身或其他任务调用。 3. vTaskDelay() :用于使当前任务进

    2024年02月12日
    浏览(37)
  • 【STM32】利用CubeMX对FreeRTOS用按键控制任务

    对于FreeRTOS中的操作,最常用的就是创建、删除、暂停和恢复任务。 此次实验目标: 1.创建任务一:LED1每间隔1秒闪烁一次,并通过串口打印 2.创建任务二:LED2每间隔0.5秒闪烁一次,并通过串口打印 3.创建任务三:通过KEY1实现对任务一的创建和删除。 按键按下以后如果有任

    2024年02月13日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包