cancel
Showing results for 
Search instead for 
Did you mean: 

sample code for STM32F411 accessing uSD card?

rwmao
Senior
Posted on October 19, 2015 at 06:16

Accessing file in a uSD card should be pretty easy.

STM32Cubemx can generate the code for you, however, I never succeed in accessing uSD with the code generated by cubemx. In my own board I have a STM32F411RC chip. In order to study uSD, I have aF4 discovery board with BB board to test uSD. A testing code was utilized to test the hardware to ensure that the hardware has no problem. The code generated by cubemx for uSD is attached. Only a few sentences were added to the main() function. I couldn't find any problem in the code. At debuging, it stops at the line:
if
(f_open(&MyFile, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
//note filename length should be <=8
Anyone, please help to check the code. All project files are attached. Only main.c file is posted on page to view. Others files were generated by cubemx, not changed at all. Or please generate a simple sample code for STM32F411RC to access uSD. I have been struggling for a few days. Really appreciate for suggestions and help.

#include ''stm32f4xx_hal.h''
#include ''fatfs.h''
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
SD_HandleTypeDef hsd;
HAL_SD_CardInfoTypedef SDCardInfo;
DMA_HandleTypeDef hdma_sdio_rx;
DMA_HandleTypeDef hdma_sdio_tx;
/* USER CODE BEGIN PV */
/* Private variables ---------------------------------------------------------*/
FATFS SDFatFs; 
/* File system object for SD card logical drive */
FIL MyFile; 
/* File object */
/* USER CODE END PV */
static
void
Error_Handler(
void
);
/* Private function prototypes -----------------------------------------------*/
void
SystemClock_Config(
void
);
static
void
MX_GPIO_Init(
void
);
static
void
MX_DMA_Init(
void
);
static
void
MX_SDIO_SD_Init(
void
);
/* USER CODE BEGIN PFP */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
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[] = 
''testing using own code. This is STM32 working with FatFs''
; 
/* File write buffer */
uint8_t rtext[100]; 
char
textbuf[200]; 
//string buffer
char
filename[]=
''testAtxt''
; 
//filename length should be <=8
/* USER CODE END 1 */
/* MCU Configuration----------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SDIO_SD_Init();
// MX_FATFS_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
if
(FATFS_LinkDriver(&SD_Driver, SD_Path) == 0) 
//no need, it was initialized in MX_FATFS_Init();
{
/*##-2- Register the file system object to the FatFs module ##############*/
if
(f_mount(&SDFatFs, (TCHAR 
const
*)SD_Path, 0) != FR_OK)
{
/* FatFs Initialization Error */
Error_Handler();
}
else
{
/*##-4- Create and Open a new text file object with write access #####*/
if
(f_open(&MyFile, filename, FA_CREATE_ALWAYS | FA_WRITE) != FR_OK) 
//note filename length should be <=8
{
/* 'STMTXT' file Open for write Error */
Error_Handler();
}
else
{
/*##-5- Write data to the text file ################################*/
res = f_write(&MyFile, wtext, 
sizeof
(wtext), (
void
*)&byteswritten);
if
((byteswritten == 0) || (res != FR_OK))
{
/* 'STMTXT' file Write or EOF Error */
Error_Handler();
}
else
{
/*##-6- Close the open text file #################################*/
f_close(&MyFile);
/*##-7- Open the text file object with read access ###############*/
if
(f_open(&MyFile, filename, FA_READ) != FR_OK)
{
/* 'STMTXT' 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))
{
/* 'STMTXT' 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 */
// BSP_LED_On(LED1);
}
}
}
}
}
}
}
/*##-11- Unlink the RAM disk I/O driver ####################################*/
FATFS_UnLinkDriver(SD_Path);
while
(1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
static
void
Error_Handler(
void
)
{
/* Turn LED3 on */
// BSP_LED_On(LED3);
while
(1)
{
}
}
/** System Clock Configuration
*/
void
SystemClock_Config(
void
)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/* SDIO init function */
void
MX_SDIO_SD_Init(
void
)
{
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;
}
/** 
* Enable DMA controller clock
*/
void
MX_DMA_Init(
void
) 
{
/* DMA controller clock enable */
__DMA2_CLK_ENABLE();
/* DMA interrupt init */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
/** Configure pins as 
* Analog 
* Input 
* Output
* EVENT_OUT
* EXTI
*/
void
MX_GPIO_Init(
void
)
{
/* GPIO Ports Clock Enable */
__GPIOH_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOA_CLK_ENABLE();
__GPIOD_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param 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
/**
* @}
*/
/**
* @}
*/

8 REPLIES 8
rwmao
Senior
Posted on October 19, 2015 at 18:20

Here is the update.

Clive1 is right. Lots of us are using uSD without the assistance of cube.

Seriously cubemx is not well-established at all.

I copied the sample code from

STM32Cube_FW_F4_V1.8.0\Projects\STM324xG_EVAL\Applications\FatFs\FatFs_uSD. Remove unnecessary BSP files.

It works on the F4 discovery board.No problem for uSD card. 

STM324xG_EVAL

natively supports STM32F407 chips. therefore it is compatible with F4 discovery board.

Now I need to migrate it to STM32F411RC chip, anyone has guideline please?

Thanks

Posted on October 19, 2015 at 18:32

The basic task is to

Address the memory map, in the linker script or scatter file

Address the vectors in the startup_stm32f4xx.s

Address the clocks in the system_stm32f4xx.c

Watch for less peripherals, slower clocks, less memory
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on October 19, 2015 at 18:49

Is there anyway to generate the file and ues?

I have excel macro for clock file.

How about

Address the memory map, in the linker script or scatter file

Address the vectors in the startup_stm32f4xx.s

Thanks

Posted on October 19, 2015 at 19:27

None of this should be unduly complicated, for the SPL it's a matter of cherry picking the right files, making sure things didn't change from the last release to accommodate new chips. Add/change the compiler command line defines to reflect the chosen part.

Not sure I need an Excel sheet to compute the clocks, the interactions/dependencies are reasonably simple.

The linker settings are going to depend on the specific part, either the tools enumerate the memory configurations for a selected part, and/or those can be pulled from the web or data sheet for the part.

Figure it's 15-30 mins of due diligence work, ensuring all the ducks are lined up correctly.

The DISCO uses the STM32F411VET6 (512KB FLASH, 128KB RAM)

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on October 21, 2015 at 05:04

Update of the code.

I switched the board from STM32F4 discovery to F411RC chip(my own board). And did the following changes. 1. Using Cubemx to generate a template project with chip F411RC. 2. Change group files using the one which was tested on F4 discovery board with uSD card. I am sure all the files are correctly replaced. 3. system_stm32f4xx, startup_stm32f411xe.s were copied from the template found in the resp folder. 4. stm32f4xx_hal_conf.h file was generated by stm32cubemx, in which module was double checked to make sure necessary modules were enabled. 5. Clock setting was updated as following.

void
SystemClock_Config(
void
) 
{ 
RCC_OscInitTypeDef RCC_OscInitStruct; 
RCC_ClkInitTypeDef RCC_ClkInitStruct; 
__PWR_CLK_ENABLE(); 
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); 
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 
RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 
RCC_OscInitStruct.PLL.PLLM = 16; 
RCC_OscInitStruct.PLL.PLLN = 192; 
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
RCC_OscInitStruct.PLL.PLLQ = 4; 
HAL_RCC_OscConfig(&RCC_OscInitStruct); 
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1 |RCC_CLOCKTYPE_HCLK 
|RCC_CLOCKTYPE_PCLK2; 
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; 
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3); 
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); 
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); 
/* SysTick_IRQn interrupt configuration */
// HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); 
}

Now I test the uSD. Find there is problem in 0690X00000605JMQAY.png Dig into the error. 0690X00000605JRQAY.png Then : 0690X00000605JWQAY.png 0690X0000060MnOQAU.gif Further suggestions please. Thanks
Posted on October 21, 2015 at 14:36

I really have no insight into your board design, or clocks. Right now it kind of suggests a connectivity issue with the SD Card, and perhaps clocks.

I can't help you with HAL stuff, and whether that works out of the box, or not.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
rwmao
Senior
Posted on October 23, 2015 at 01:19

Maybe it is caused by speed. When I debug one line by one line, it seems OK.

How can I reduce the SDIO speed?

Thanks

Posted on October 23, 2015 at 05:09

The primary clock is from the Q tap of the PLL, the one controlling the bus is the ClockDiv parameter for the SDIO. The initialization speed is 400 KHz, and most microSD cards should be clockable at 24 MHz

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..