Skip to main content
Jack3
Senior
May 9, 2019
Question

STM32H7 and u-SD card on sdmmc1 - Using STM32CubeMX and HAL

  • May 9, 2019
  • 6 replies
  • 5779 views

Dear friends,

I'm Using STM32Cube_FW_H7_V1.4.0 with TrueStudio 9.3.0, on an STM32H753.

Has anybody got an micro-SD card working on the SDMMC1 peripheral for an STM32H7?

For my it, seems to come with a Timeout error.

I initialized it like:

void MX_SDMMC1_SD_Init(void)
{
 HAL_StatusTypeDef status;
 
 hsd1.Instance = SDMMC1;
 hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
 hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
 hsd1.Init.BusWide = SDMMC_BUS_WIDE_1B;
 hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
 hsd1.Init.ClockDiv = 2; // 0 - 1023
 status = HAL_SD_Init(&hsd1);
 if (status != HAL_OK)
 {
 dmc_puts("!HAL_OK\n");
 _Error_Handler2(__FILE__, __LINE__, status);
// Error_Handler();
 }
}
 
void HAL_SD_MspInit(SD_HandleTypeDef* sdHandle)
{
 
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 if(sdHandle->Instance==SDMMC1)
 {
 /* USER CODE BEGIN SDMMC1_MspInit 0 */
 
 /* USER CODE END SDMMC1_MspInit 0 */
 /* SDMMC1 clock enable */
 __HAL_RCC_SDMMC1_CLK_ENABLE();
 
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOD_CLK_ENABLE();
 
 /**SDMMC1 GPIO Configuration 
 PC8 ------> SDMMC1_D0
 PC9 ------> SDMMC1_D1
 PC10 ------> SDMMC1_D2
 PC11 ------> SDMMC1_D3
 PC12 ------> SDMMC1_CK
 PD2 ------> SDMMC1_CMD 
 */
 
 GPIO_InitStruct.Pin = SD_D0_Pin|SD_D1_Pin|SD_D2_Pin|SD_D3_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
 GPIO_InitStruct.Pin = SD_CK_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(SD_CK_GPIO_Port, &GPIO_InitStruct); // GPIOC
 
 GPIO_InitStruct.Pin = SD_CMD_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
 HAL_GPIO_Init(SD_CMD_GPIO_Port, &GPIO_InitStruct); // GPIOD
 
 /* SDMMC1 interrupt Init */
 HAL_NVIC_SetPriority(SDMMC1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
 /* USER CODE BEGIN SDMMC1_MspInit 1 */
 
 /* USER CODE END SDMMC1_MspInit 1 */
 }
}

The call MX_SDMMC1_SD_Init(); was missing the lines to call HAL_SD_Init(&hsd1);, which I added.

I printed some messages, which I added to the HAL Libraries:

MX_SDMMC1_SD_Init

SDMMC_ERROR_TIMEOUT

ERROR: SD_PowerON

ERROR: HAL_SD_InitCard

!HAL_OK

Besides 4-bit mode, I tried 1-bit mode, and I experimented with the clock speed.

And I tried different SD Cards, all with the same result.

What can I check?

My source code is also on github, I will comment back and update it once it works, so it can help others.

https://github.com/bkht/STM32_SD_SDMMC

I have used an eMMC on SDMMC (8-bit) on an STM32F7, but this SD Card (4-bit) is on an STM32H7.

This topic has been closed for replies.

6 replies

sirius506
Associate III
May 15, 2019

Are you using SD card transceiver?

CubeMX generated code assumes use of the transceiver (as found on ST eval board.)

If you don't have transceiver on your target board, change your stm32h7xx_hal_conf.h file as shown below and see if it works.

It works for my target board.

#define USE_SD_TRANSCEIVER 0U /*!< uSD Transceiver is NOT used */

CubeMX should have transceiver configuration option on its "parameter settings" tab.

Toshiharu

Jack3
Jack3Author
Senior
May 22, 2019

Hi Toshiharu, thank you! This is very useful information. At the moment, the board is back at the company who made the prototype, to get a Revision 'V' of the STM32H753VIT6, as there was a list errata for the SDMMC in the 'Y' version we got, which all seem fixed in 'V'. I will need to wait to get it back. As soon as I have it, I will test this.

Senior
May 19, 2019

I'm also having troubles with SDMMC and uSD on H743 and H750 boards. My code is set to Mode SD 4 bits at 200 MHz from PLL2R and clock divide factor as 8 (no transceiver, so "USE_SD_TRANSCEIVER 0U"). Using a SanDisk 4GB Class 4 card, everything works fine. Using a SanDisk 8GB Class 4 card, it fails on "identify card operating voltage", returning HAL_SD_ERROR_CMD_RSP_TIMEOUT on "SD_PowerON" method.

I noticed some code changes from Cube FW 1.3.2 and 1.4.0, but both have the same result.

Jack3
Jack3Author
Senior
May 22, 2019

Hi Peaga, I also notices the changes between the version, I moved to the last one, the result is more consistent: at least all cards seem to have the same problem now. I don't have my board at the moment, but hope to get it back soon, I hope with a revision 'V' chip, instead of revison 'Y'.

What version is your chip?

Please also refer to:

https://www.st.com/en/microcontrollers-microprocessors/stm32h743-753.html#resource

Senior
May 26, 2019

Hello Jack, thanks!

It turns out to be something with my bootloader (external flash). Running the main app without it, any SD card works fine... I'll study it a little more!

Tim Russell
Associate II
May 21, 2019

I'm having similar problems getting the uSD (SDMMC1) interface to work on my H7.

I recently upgraded from an F7 (where the uSD was working) to the H7.

I am getting an error in the HAL_SD_Init() function.

I'm using the same CubeMX settings as used with the F7 with no success.

I also modified USE_SD_TRANSCEIVER=0U (for no transceiver).

Jack3
Jack3Author
Senior
May 22, 2019

Hi Tim, it seems very related to my problem. Yet, I can't try Toshiharu's suggestion/solution, as I have to wait for my board to come back with hopefully a revision 'V' chip. What version is your chip? You can see it at the top, or determine it by software:

uint8_t GetMcuRevIDChar(void)
{
 // Reference Manual, June 2018, page 3131 of 3247
 // Bits 31:16 REV_ID[15:0]: Revision
 // 0x1001 = Revision Z
 // 0x1003 = Revision Y
 // 0x2001 = Revision X
 // 0x2003 = Revision V - (See STM32H750/753 Errata sheet, device limitations)
 
 uint32_t ID_Code = DBGMCU->IDCODE;
 uint16_t Dev_ID = ID_Code & 0x0fff;
 uint16_t Rev_ID = (ID_Code >> 16);
 if (Rev_ID == 0x1001)
 return 'Z';
 if (Rev_ID == 0x1003)
 return 'Y';
 if (Rev_ID == 0x2001)
 return 'X';
 if (Rev_ID == 0x2003)
 return 'V';
 return '-';
}

Jack3
Jack3Author
Senior
May 24, 2019

I found that CubeMX is assuming the STM32H7 eval board. Because I don't use an SD bus tranceiver, In stm32h7xx_hal_conf, I had to set this option like below:

#define USE_SD_TRANSCEIVER 0U /*!< uSD Transceiver is NOT used */

I took a Nucleo-H743ZI and created a small CubeMX poject for it with sdmmc, which now works great, and put the code on github. I hope it helps others.

I do not use a card detect switch, so I made sure BSP_SD_IsDetected always returns SD_PRESENT, and so disk_initialize gives no error.

It works a little bit, but I have this problem:

disk_initialize, disk_status, f_mount and f_getfree return no errors and seem to work fine.

Reading a file works too, but f_write did hang at first, when HAL_SD_WriteBlocks was called. It hung in the while loop.

When I printed dots in the while loop it succeeded, probably because of the delay that it caused.

For now I added a __NOP() in a loop, then all works fine.

It needed a minimum of 25 iterations, when hsd1.Init.ClockDiv = 3;

Decreasing ClockDiv makes the card faster, hence we need less NOPs, which makes sense. Varying the PLLQ ratio does not influence the delay.

Update: I decovered, hsd1.Init.ClockDiv should be less the 6, to avoid writing blocks to hang. Below 6, no delay is required in the function HAL_SD_WriteBlocks . I now have set it to 2.

All seems to work now, I will test a bit more.

Once all seem solved, I will update hithub to help others.

MX_SDMMC1_SD_Init
MX_FATFS_Init
SDPath: 0:/
Initialize disk: OK
Disk status: OK
Mount disk: OK
Volume label:
 31248384 kB total disk space
 31248032 kB available
Read file Info.txt
Hello SD Card.
Close file
Create file hello.txt
Set file timestamp of hello.txt
Append file hello.txt
Set file timestamp of hello.txt
Create file hello2.txt
Set file timestamp of hello2.txt

The code is here:

https://github.com/bkht/Nucleo-H743ZI_SDMMC

So to make f_write not hang, I configured hsd1.Init.ClockDiv = 2; (less then 6 at least!).

It looks like all is working well, I added long file name in FatFs.

I updated github, to help others. =)

Thanks all for bearing with me!

jakob.brunhart
Associate III
May 24, 2019

Hi Jack

I'm using NUCLEO-H743ZI and uVision 5.27. My SD-Card seems to work now. But I also had problems. The first was the #define USE_SD_TRANSCEIVER 0U which was set to 1U. But you've already found that mistake. I assume that you are also using a filesystem. In the file FS_Config_MC_0.h there is a define which defines the DMA Buffer base address. I had to set to the follwing

#define MC0_CACHE_ADDR     0x24000000

Perhaps this helps also: https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

Regards

Jakob

Garnett.Robert
Senior III
January 25, 2020

Hi,

I have got an SD Card working with an STM32H743VITX.

You can find a copy of the complete project in the share part of this community (https://community.st.com/s/group/0F90X000000AXrvSAG)

Initially I had a bit of trouble getting the SD Card to work as I was using an SD Card with a Nucleo 144 H7 with hookup wire between the sd socket and the processor board.

The HAL SD card drivers use automatic speed setting and as I was using high speed SD cards the bus clock was being set to 50+ MHz. Of course the wiring betwwen the sd card and the processor was skewing the clock so badly it failed. I went in an hacked the code to prevent the speed from automatically being set and I found with the breadboard setup I could get the card working reliably at 12 MHz. if you look for the comment rjgDebug or rjgMod in the code you will find the hacks I made.

When I manufactured the power monitor project and had equal track lengths to the sd card I could push the clock speed up to 100 MHz with the right SD card and get reliable operation. I am currently running the SD Card at 50 MHz.

I bolted sqLite into the software system and have had reasonable success with this, but I am getting random errors after a few thousand transactions. There is no database corruption occurring as I am using the Write Ahead Log (WAL) to manage transactions.

I am in the process of debugging this and when I sort it out I will update the project in the shared area. The project I posted is a bit of a dog's breakfast as I have had to do a lot of experimentation to get it all to work.

A fragment of debug output is shown below:

00> Insert Started
00> vfsDirectWrite = 0 File Handle = 24060C80
00> Disk fatFS Write OK Res = 0 Disk LUN = 0 Buff = 24060CD4 Sector = 395856 count = 1 
00> Disk fatFS Write OK Res = 0 Disk LUN = 0 Buff = 24004418 Sector = 395857 count = 7 
00> Disk fatFS Read OK Res = 0 Disk LUN = 0 Buff = 24060CD4 Sector = 395864 count = 1 
00> vfsDirectWrite = 0 File Handle = 24060C80
00> vfsDirectWrite = 0 File Handle = 24060C80
00> Disk fatFS Write OK Res = 0 Disk LUN = 0 Buff = 24060CD4 Sector = 395864 count = 1 
00> Disk fatFS Write OK Res = 0 Disk LUN = 0 Buff = 2400C900 Sector = 395865 count = 7 
00> Disk fatFS Read OK Res = 0 Disk LUN = 0 Buff = 24060CD4 Sector = 395872 count = 1 
00> vfsDirectWrite = 0 File Handle = 24060C80
00> Step Done
00> SqLite Mem Hi Water Mark = 294400
00> Insert Complete

The file handle xxxx80 is the WAL file, the file handle xxxx118 is the main sqLite database file.

Using sqLite is a lot better than logging data to raw files although it does need a lot of ram. My system is using around 300 k of heap for sqLite. I have allocated 420K in the AXI ram dedicated to the sqLite heap using memsys5.

It would be nice if ST added sqLite to MX cube for use with the larger processors and included a Virtual File System that interfaces between fatFS, sqLite and SD Cards.

Best regards

Rob