2024-05-27 04:08 PM - edited 2024-05-27 04:37 PM
Has anyone successfully used STM32f407 for reading and writing SD card using SDIO? I tried creating a project with SDIO using stm32f407 with a bit of code from the sample project of FatFS_uSD using (stm32F413). And I keep getting a timeout error from the function SDMMC_GetCmdResp1.
Here's my main code:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "fatfs.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
SD_HandleTypeDef hsd;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
FATFS SDFatFs; /* File system object for SD card logical drive */
FIL MyFile; /* File object */
//char SDPath[4]; /* SD card logical drive path */
static uint8_t buffer[_MAX_SS]; /* a work buffer for the f_mkfs() */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SDIO_SD_Init(void);
static void MX_USART2_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "This is STM32 working with FatFs"; /* File write buffer */
uint8_t rtext[100]; /* File read buffer */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SDIO_SD_Init();
/*MX_USART2_UART_Init();
MX_FATFS_Init();*/
/* USER CODE BEGIN 2 */
/*##-1- Link the micro SD disk I/O driver ##################################*/
if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
{
/*##-2- Register the file system object to the FatFs module ##############*/
if(f_mount(&SDFatFs, (TCHAR const*)SDPath, 0) != FR_OK)
{
/* FatFs Initialization Error */
Error_Handler();
}
else
{
/*##-3- Create a FAT file system (format) on the logical drive #########*/
/* WARNING: Formatting the uSD card will delete all content on the device */
if(f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, buffer, sizeof(buffer)) != FR_OK)
{
/* FatFs Format Error */
Error_Handler();
}
else
{
/*##-4- Create and Open a new text file object with write access #####*/
if(f_open(&MyFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
{
/* 'STM32.TXT' file Open for write Error */
Error_Handler();
}
else
{
/*##-5- Write data to the text file ################################*/
res = f_write(&MyFile, wtext, sizeof(wtext), (void *)&byteswritten);
/*##-6- Close the open text file #################################*/
if (f_close(&MyFile) != FR_OK )
{
Error_Handler();
}
if((byteswritten == 0) || (res != FR_OK))
{
/* 'STM32.TXT' file Write or EOF Error */
Error_Handler();
}
else
{
/*##-7- Open the text file object with read access ###############*/
if(f_open(&MyFile, "STM32.TXT", FA_READ) != FR_OK)
{
/* 'STM32.TXT' file Open for read Error */
Error_Handler();
}
else
{
/*##-8- Read data from the text file ###########################*/
res = f_read(&MyFile, rtext, sizeof(rtext), (UINT*)&bytesread);
if((bytesread == 0) || (res != FR_OK))
{
/* 'STM32.TXT' file Read or EOF Error */
Error_Handler();
}
else
{
/*##-9- Close the open text file #############################*/
f_close(&MyFile);
/*##-10- Compare read data with the expected data ############*/
if((bytesread != byteswritten))
{
/* Read data is different from the expected data */
Error_Handler();
}
else
{
/* Success of the demo: no error occurrence */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
}
}
}
}
}
}
}
}
/*##-11- Unlink the RAM disk I/O driver ####################################*/
FATFS_UnLinkDriver(SDPath);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief SDIO Initialization Function
* None
* @retval None
*/
static 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_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
/* USER CODE BEGIN SDIO_Init 2 */
/* USER CODE END SDIO_Init 2 */
}
/**
* @brief USART2 Initialization Function
* None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_RESET);
/*Configure GPIO pin : PE7 */
GPIO_InitStruct.Pin = GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pins : PD14 PD15 */
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* file: pointer to the source file name
* line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
Most of the code was generated using STM32CubeIDE, the only thing I borrowed from the sample project is between user code begin and end 2.
I'm getting the timeout error (4) from this function SDMMC_CmdBlockLength.
2024-05-29 07:48 AM
Hello @KL_UOA
You are missing to call the function HAL_SD_Init() to initialize the SD
/**
* @brief SDIO Initialization Function
* @param None
* @retval None
*/
static 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 = 0;
if (HAL_SD_Init(&hsd) != HAL_OK)
{
Error_Handler();
}
if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SDIO_Init 2 */
/* USER CODE END SDIO_Init 2 */
}
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-05-30 08:35 PM - edited 2024-05-30 08:37 PM
Thanks, FBL, unfortunately, that didn't help, I'm still getting 4 from errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE). I had no problem with SD_InitCard(hsd); and SD_PowerON(hsd) before that.
2024-05-31 04:05 AM
HI @KL_UOA
Would you share your project to reproduce on my end?
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-06-04 08:55 PM - edited 2024-06-04 09:24 PM
2024-06-06 09:07 PM
2024-06-07 05:27 AM
Hello,
Have you got a chance to try the code yet?
What is the board you're using? ST board? if custom board not possible to try it.
2024-06-07 06:40 AM
I tried testing it with a STM32F407 board, didn't work. Although I'm not sure if that's an official ST board, it's black, but it's got a ST logo on it.
But the code really only has SDIO configuration and the simplest operation. Why would it work on an official board and not on others. What has to be on the board for it to work?
2024-06-07 09:03 AM
Hi @KL_UOA
Sorry for not reaching out sooner, it would seem more interesting if you could provide us further details about your hardware setup? board? reference?
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-06-07 11:14 PM
I've tested with a board we bought:
I doubt that this is an official ST board, even though the ST label is on it. The MCU on the board is STM32F407ZE. I've also tested with a custom-made board, with STM32F407VE. Here's the relevant part of the schematic:
I've got the same result from both boards. Is there anything from the board that could result in the issue I found?