cancel
Showing results for 
Search instead for 
Did you mean: 

SDIO 4Bit Mode, FatFS, and STM32CubeMX on STM32F401 Discovery

coppercrimp
Associate III
Posted on January 20, 2015 at 17:52

I’ve been struggling to get SDIO 4 Bit mode working on my STM32F401 Discovery. I can get everything working fine in SDIO 1 Bit mode.

I’ve seen similar posts on this topic but they don’t seem to help much.

I’ve modified the STM32F401 Discovery with an SD Card holder wired to the proper pin breakouts. I’ve removed all components from the board that interfere with these signals.

I use STM32CubeMX 4.5 to generate the base code for my project. All I’m trying to do at the moment is open a text file and write a string to it. Again, this works in 1 Bit Mode, but not in 4 Bit.

I’ve tried using both a 400kHz and 24MHz SDIO_CK. Neither clock speed works in 4 Bit Mode. Both clock speeds work in 1 Bit Mode.

The code seems to fail when calling HAL_SD_SendSDStatus() in stm32f4xx_hal_sd.c. This function fails when called during SD_initialize() routine. HAL_SD_SendSDStatus() returns value SD_START_BIT_ERR

I’d be very grateful to anyone who can help me troubleshoot this issue.

Best regards,

Rob

10 REPLIES 10
coppercrimp
Associate III
Posted on January 20, 2015 at 18:11

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6h2&d=%2Fa%2F0X0000000btO%2FgeZezYFDThH4tDwaCqZj94CIUJTw7KOGu.KXYoWUxCs&asPdf=false
Posted on January 20, 2015 at 18:19

Hi Rob,

The generated code using the STM32CubeMX of the SDIO 4bit bus wide configuration presents a limitation. Otherwise, it's recommended to configure first the 1-bit SD Data Transfer Mode:

tmpinit.BusWide = SDIO_BUS_WIDE_1B;

And then, just enable wide operation, for the 4-bit SD Data Transfer Mode:

HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B);

You can refer toBSP_SD_Init() function under stm324x9i_eval_sd.c BSP driver within the

http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1897/PF259243#

Regards, Heisenberg.
coppercrimp
Associate III
Posted on January 20, 2015 at 20:37

Thanks Heisenberg. If you could give me some more detail on how to fit this into the framework of code generated by CubeMX it would be very helpful

Posted on January 21, 2015 at 09:15

Hi Rob,

STM32CubeMX team are aware of  this limitation. Just keep an eye out for the next updates!

Please continue providing valuable feedback.

Regards,

Heisenberg.

craig2399
Associate II
Posted on January 27, 2015 at 02:42

Heisenberg,

I too ran into this issue and initially had some success with your suggested solution. However I wrote some tests to determine write speeds and had the 4-bit mode intermittently fail. 1-bit mode worked fine. I am running on our custom board with an STM32F405-RGT6, using a Kingston micro sd card, 4GB speed class 4. The FatFs example application runs fine on our board with just minor configuration changes (clock). My test is pretty simple. Write an 8MB file using the following chunk sizes (1k, 2k, 4k,...64k), overwriting the same file each time. If I just run a couple of the tests, it will often succeed in 4-bit mode. But try to run more than 3 of the tests, it will fail when opening a file for writing with an FRESULT ==FR_DISK_ERR. In 1-bit mode, it succeeds every time. Please note that I am using the STM32CubeMX app for configuring my hardware and generating the project file. Because of this, I needed to configure the SDIO in 4-bit mode so all the pins get configured by CubeMX. However, in main I change the field in the init struct to 1-bit, then link the driver:

/* USER CODE BEGIN 2 */
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
/* USER CODE END 2 */
/*## FatFS: Link the SD driver ###########################*/
retSD = FATFS_LinkDriver(&SD_Driver, SD_Path);

...then right after mounting the file system, set to 4-bit mode:

static void SD_mount() {
FRESULT mountResult = f_mount(&fs, (TCHAR const*)SD_Path, 1);
assert(mountResult == FR_OK);
HAL_SD_WideBusOperation_Config(&hsd, SDIO_BUS_WIDE_4B);
}

After mounting the sd card, I run my test. Here is some of the generated configuration code for ref: From main.c:

/** 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_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 10;
RCC_OscInitStruct.PLL.PLLN = 210;
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);
}
/* 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_4B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 0;
}

...and fromstm32f4xx_hal_msp.c:

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 */
__SDIO_CLK_ENABLE();
/**SDIO GPIO Configuration
PC8 ------> SDIO_D0
PC9 ------> SDIO_D1
PC10 ------> SDIO_D2
PC11 ------> SDIO_D3
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_sdio_rx.Instance = DMA2_Stream6;
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_VERY_HIGH;
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;
HAL_DMA_Init(&hdma_sdio_rx);
__HAL_LINKDMA(hsd,hdmarx,hdma_sdio_rx);
hdma_sdio_tx.Instance = DMA2_Stream3;
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_VERY_HIGH;
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;
HAL_DMA_Init(&hdma_sdio_tx);
__HAL_LINKDMA(hsd,hdmatx,hdma_sdio_tx);
/* System interrupt init*/
HAL_NVIC_SetPriority(SDIO_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
/* USER CODE BEGIN SDIO_MspInit 1 */
/* USER CODE END SDIO_MspInit 1 */
}
}

Any thoughts? Thanks, Craig
coppercrimp
Associate III
Posted on January 27, 2015 at 18:29

Hi Craig,

Have you tried enabling hardware flow control on SDIO? Maybe that would make things more reliable.

When writing the 64k data chunks to the SD Card, where are you buffering that data? Is it stored as an array in on chip SRAM? If so you must be using a huge part

craig2399
Associate II
Posted on March 24, 2015 at 00:34

Hi Rob,

Thanks for the reply and sorry for getting back after so long.  I don't remember getting a notification that anyone replied to my post.

At any rate, no I have not tried HW flow control on the SDIO.  There is an errata that says it should not be used:

http://www.st.com/web/en/resource/technical/document/errata_sheet/DM00037591.pdf

Ultimately I stayed with 1-bit mode.  It is fast enough for what I need to do.

As for the 64k buffer, I just created it statically in my module.  This was just a test program with very little code so there was enough ram to do this.  I wouldn't be able to do this in our production firmware.

Do you have 4-bit mode working for you now?

Craig

Posted on March 24, 2015 at 03:08

All the F405/407 parts have 128KB of SRAM, plus 64K of CCMRAM, it is the F401 parts that are limited, less ADC, TIM, RAM, speed, etc.

Both the STM32F4-DISCO and STM32F401-DISCO boards can run 4-bit SDIO, using the STM32F4-DIS-BB board, or similar hand wiring, without removing any components. Output via USART6 PC6/PC7 Even running the boards at 42 MHz I can get some pretty serviceable speeds. Writing tends to be constrained by the quality/rating of the card and the underlying controller/NAND array.

FatFs Testing for asr.ahmed STM32 Forum
---- 0 /DIR.TXT
---- 4 /LENGTH.TXT
---- 125 /LOG.TXT
---- 32768000 /SPEEDTST.BIN
---- 2419206 /1.BMP
Done
STM32 1024 KB FLASH, 192 KB RAM, 00240021-34314719-36343236 UNIQUE
SYS:42000000, H:42000000, P1:42000000, P2:42000000
CPU:42000000, SDIO:48000000,24000000
CRC32 C47004E3 Memory Image
32768000 Bytes, 481981050 Cycles
2.855415 MBps Write (FatFs)
CRC32 C47004E3 SPEEDTST.BIN
32768000 Bytes, 487387505 Cycles
2.823741 MBps Write (FatFs)
CRC32 C47004E3 SPEEDTST.BIN
32768000 Bytes, 145517716 Cycles
9.457653 MBps Read (FatFs)
32768000 Bytes, 145511631 Cycles
9.458048 MBps Read (FatFs)
Done

The issue here is probably with the HAL/Cube methodology, a .HEX using the SPL is provided about halfway down [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Discovery/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Discovery/sdio%20fatfs%20speed%20problem&FolderCTID=0x01200200770978C69A1141439FE559EB459D75800084C20D8867EAD444A5987D47BE638E0F&currentviews=1226]this thread if you want to sanity check your connections.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
coppercrimp
Associate III
Posted on March 30, 2015 at 19:06

Hey Craig,

I have been using SDIO 4 Bit mode with FIFO and hardware flow control enabled. I used the method you described in your previous post to get it working, so thanks for helping out! I also switched to the STM32F407 (was previously using the STM32F401).

My application reads a audio ADC sampling at 192kHz 16bit and writes it to an SD card using FAT32. So the data rate is fairly high. So far it seems to be working reliably using SDIO 4 bit mode