赞
踩
以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; }
此时,卡死问题就会解决。
进行实际读写测试:
调试发现能够正常读写,本次分享到此结束。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。