2017-01-15 03:45 PM
I have two boards designed for stm32f405 and stm32f411 to test uSD card.
The problem of using uSD on STM32F405 was fixed as discussed earlier:
https://community.st.com/thread/35991-microsd-card-problem-bug-in-the-filestm32f4xxhalsdc
Reading file/writing file are totally fine withut any problem on the STM32F405.Then I study the another board with a chip stm32f411ret6. These two boards are very similar because these two chips has very close pin configration.
Here is what is going on on the board with the chip stm32f4
I generated the code with cubemx, copy the testing code, and fixed the bug in the file mentioned above.
Low level io writing/reading has been tested. Pass!
Can I say that hardware problem (such as connection)is out of question?
But when I try to use file system to read/write file, there is an error in the line:
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */
returns FR_DISK_ERR.
Tried two sd card, 1g and 32g. Both works on the board with chip stm32f
What is wrong? Any instructions please.
The code for reading/writing testing is as followings
void SD_Test_LowLevel(void) { uint8_t SD_state = MSD_OK; static uint8_t prev_status = 0; char usbbuffer[200]; SD_state = BSP_SD_Init(); if(SD_state != MSD_OK) { sprintf(usbbuffer,'\n---initialize failed ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back Error_Handler(); } //initialization is done. Now go ahead for SD operation in low level SD_state = BSP_SD_Erase(BLOCK_START_ADDR, (BLOCKSIZE * NUM_OF_BLOCKS)); if(SD_state != MSD_OK) { sprintf(usbbuffer,'\n---erase failed ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back Error_Handler(); } /* Fill the buffer to write */ Fill_Buffer(aTxBuffer, BUFFER_WORDS_SIZE, 0x22FF); SD_state = BSP_SD_WriteBlocks(aTxBuffer, BLOCK_START_ADDR, BLOCKSIZE, NUM_OF_BLOCKS); if(SD_state != MSD_OK) { Error_Handler(); } SD_state = BSP_SD_ReadBlocks(aRxBuffer, BLOCK_START_ADDR, BLOCKSIZE, NUM_OF_BLOCKS); if(SD_state != MSD_OK) { sprintf(usbbuffer,'\n---reading failed ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back } else { sprintf(usbbuffer,'\n---Reading OK ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back if(Buffercmp(aTxBuffer, aRxBuffer, BUFFER_WORDS_SIZE) > 0) { sprintf(usbbuffer,'\n---reading/writing compare failed ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back } else { sprintf(usbbuffer,'\n---Testing is done, OK ---\n');//export it to char buffer first. SendTextMsgToUSB(usbbuffer); //send the txt back } } GREEN_LED_ON;//Good while (1) { } }�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
#stm32f411 #sdio #stm32f405
Note: this post was migrated and contained many threaded conversations, some content may be missing.
2017-01-16 04:12 AM
Hi mao,
1- I confirm that there is a bug in the implementation of
SD_PowerON. As already said in
https://community.st.com/0D50X00009XkeRpSAJ
, this will be fixed in all packages.2- Referring to datasheets of both products (
& ), we see that SDIO doesn't have the same characteristics (table 'Dynamic characteristics: SD / MMC characteristics'). So you have to pay attention to clock configuration mainly.3- If you try to use same PCB for both products, make sure that you select same pins using CubeMX. In fact, there are other possible pins for STM32F411 chips compared to STM32F405 ones.
Please keep us updated about your finding.
-Amel
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.
2017-01-16 05:42 AM
And which low level read is failing with an error? View what DISKIO.C layer is returning. Make sure DMA is 32-bit aligned.
I've used SDIO/FATFS on an STM32F411E-DISCO. Make sure you are clocking the Q PLL at an appropriate speed, supposing it is as USB is working. Check other bus clocks, and response of DMA/SDIO IRQs
2017-01-16 01:52 PM
My fault. It still have problem to for low level block reading. I tested again with low level reading. Error occurs inHal_SD_readblocks().
USB(CDC) is working well. I can see the debug string sent to the com port via USB. I guess clock should be fine. Can you help check the clock setting?
For block reading/writing, I tested in above code. Erasing/writing is fine. But stops at reading.
1. I find the problem is in the
BSP_SD_ReadBlocks
uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks)
{
if(HAL_SD_ReadBlocks(&hsd, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK)
{
return MSD_ERROR;
}
else
{
return MSD_OK;
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2. further trace into the Hal_SD_readblocks(), it comes to:
else if (__HAL_SD_SDIO_GET_FLAG(hsd, SDIO_FLAG_STBITERR))
{
__HAL_SD_SDIO_CLEAR_FLAG(hsd, SDIO_FLAG_STBITERR);
errorstate = SD_START_BIT_ERR;
return errorstate;
} �?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
Clock setting:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
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();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|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_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2017-01-17 09:29 AM
Hello Amel
Thanks for your reply.
I am using the same PCB board. By default, STM32F405 and F411 uses different pin in cubemx. Therefore I put a jump for those pins they are different in two chips. The jump is using solder iron to fix it permanently, very solid.
But I will try to alternate the pin configuration to use same pcb layout. and try what is going on.
2017-01-17 09:49 AM
>>
Can you help check the clock setting?
Clock settings look to be OK.
What Pin are you using for the Card Detect pin of the socket?
If you have details of pins, USARTs and LEDs, I could build a demo using the SPL
2017-01-19 12:06 PM
What is the SDIO clk divider set too ? try to slow down clk see if it help.
Are all pin assigned to sdio set to fast ? enabling internal pull-up may help if onboard pull up are to weak.
With flying wired SD connection and unadapted pull up i remenber to get of errors if going too fast
specialy In PIO mode too fast SDIO clock lead to random fail and issue soon or late
Last time i used CubeMX for SDIO + FaftFS or MSC/SD usb it was only generating 'PIO' code and defautl pin setutp was not best possible (i did look at some working F4 example to copy the init )
Use of DMA was key to get reliable and fast access .
That where the few things i had play on a diocveryf4 wired to an uSd adapter with weak pullup on lines for prototyping purpose .
The final board design with SD socket on board good pull up value did run smoothly and reliably at almost full SDIO speed (using DMA).
2017-01-19 02:13 PM
We've used external pull-ups place close to the socket, I've used a couple of GHI boards using the internal pull-ups
The BYPASS mode of the SDIO doesn't work properly (timing errata), so usually the SDIO CLK is DIV2 (ie 24 MHz from a 48 MHz clock). As I recall all SD cards are rated as 25 MHz, and all the MicroSD as 50 MHz. Probably don't need 100 MHz slew-rate, 25 or 50 would suffice if there is a lot of overshoot.
If you don't use USB the SDIO peripheral can clock at 75 MHz, yielding a 37.5 MHz pin clock.
Using DMA here also.
2017-01-19 06:28 PM
Hello Sanches,
I tested with very low speed 400kHz. doesn't work. Initialization is OK, erasing/writing is fine. Error at reading.
further trace into the Hal_SD_readblocks(), it comes to:
else if (__HAL_SD_SDIO_GET_FLAG(hsd, SDIO_FLAG_STBITERR))
{
__HAL_SD_SDIO_CLEAR_FLAG(hsd, SDIO_FLAG_STBITERR);
errorstate = SD_START_BIT_ERR;
return errorstate;
}
I have a pull up resistor 47k connected for eachpin except the clock.
Actually I use the same board tested for F405 chip. everything is OK for that chip.
As I mentioned earlier, these two chips are so close. So I just use jump to alternate the routing to accomodise both chips.
In the application level, I use same code except the pin configuration.
I don't know what is difference in the low level.
2017-01-19 06:39 PM
Clive,
I am using USB to output data. I tested the speed of 400kHz. stuck in reading block.
DMA is used
void HAL_SD_MspInit(SD_HandleTypeDef* hsd)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hsd->Instance==SDIO)
{
/* USER CODE BEGIN SDIO_MspInit 0 */
/* USER CODE END SDIO_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SDIO_CLK_ENABLE();
/**SDIO GPIO Configuration
PA6 ------> SDIO_CMD
PB15 ------> SDIO_CK
PC8 ------> SDIO_D0
PC9 ------> SDIO_D1
PA9 ------> SDIO_D2
PC11 ------> SDIO_D3
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_sdio_rx.Instance = DMA2_Stream3;
hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_rx.Init.Mode = DMA_PFCTRL;
hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
hdma_sdio_tx.Instance = DMA2_Stream6;
hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4;
hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hdma_sdio_tx.Init.Mode = DMA_PFCTRL;
hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4;
hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4;
if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SDIO_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
/* USER CODE BEGIN SDIO_MspInit 1 */
/* USER CODE END SDIO_MspInit 1 */
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?