cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to reliably use SD card with SDMMC2 using M4 core of NucleoH755-ZI

MJack.1
Associate III

Hi there,

I am trying to read and write to an SD card using SDMMC2 from the M4 core on an STM32H755, using an NucleoH755-ZI and a custom SD card shield.

The shield connections are simple, short traces, and as follows:

SDMMC2_CK -> PD6

SDMMC2_CMD -> PA0

SDMMC2_D0 -> PB14

SDMMC_D1 -> PB15

SDMMC_D2 -> PB3

SDMMC_D3 -> PB4

  • All SD card pins have 47k pullup resistors to 3v3, except for the clock line.
  • The card is powered with 3v3.
  • There is no external transceiver.
  • I have removed Nucleo R75 to ensure PB14 is not connected to the Nucleo red LED.
  • I have checked that Nucelo SB81 is not connected to ensure that PA0 is not connected to the Nucleo user switch.
  • I have configured with project in CubeMX to have a sensible SDMMC clock (6MHz) and confirmed it with a scope.

Attached are pictures of my SDMMC2 settings, and my FatFS settings.

Here is the code I am using, taken from this tutorial by ST: https://www.youtube.com/watch?v=I9KDN1o6924

FRESULT res; /* FatFs function common result code */
uint32_t byteswritten, bytesread; /* File write/read counts */
uint8_t wtext[] = "Hellooo?"; /* File write buffer */
uint8_t rtext[_MAX_SS];/* File read buffer */
 
// f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, rtext, sizeof(rtext));
 
if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
{
  Error_Handler();
}
else
{
  FATFS* fs_ptr = &SDFatFS;
  volatile uint32_t freeBytes;
 
  if(f_open(&SDFile, "FILETEST0.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
  {
	  Error_Handler();
  }
  else
  {
	  //Write to the text file
	  res = f_write(&SDFile, wtext, strlen((char *)wtext), (void *)&byteswritten);
	  if((byteswritten == 0) || (res != FR_OK))
	  {
		//  Error_Handler();
	  }
	  else
	  {
		  f_close(&SDFile);
	  }
  }
}

 There is ofcourse also the Cube generated code including:

  • MX_SDMMC2_SD_Init();
  • MX_FATFS_Init();

Problem 1

The SD card fails to initialise, resulting in a time-out.

This was eventually solved by adding a 1ms delay to line 3084 of stm32h7xx_hal_sd.c (in SD_PowerON()), in the while loop when determining the card's operating voltage. It is not filling me with confidence that a 1ms magically makes this works reliably, and does not work at all without it. While it seems to be fixed, perhaps this is indicative of a larger issue.

Problem 2

The card cannot be read or written.

inside f_open, find_volume (inside ff.c) always fails, returning 'FR_NO_FILESYSTEM'.

f_mount returns success with a delayed mount, but failuer with immediate mount option.

The 4GB SDHC card has been formatted with FAT (I have also tried FAT32), with an allocation size of 4096 ( I have also tried 1024, 2048, and 8192). I have also tried deleting the volume and using f_mkfs to format the SD card, as shown in the commented out line in the code above. The result is always the same.

I have also tried all of the above with another 2GB SD card. Both cards work fine on my PC.

Things I have tried, to no avail:

  • Various SDMMC clock frequencies
  • 10k external pullups on SD lines
  • internal pullups on SD lines
  • Checked the card detect function is working correctly
  • Checked that SDMMC2 DMA and M4 both have access to all RAM regions
  • Increasing _VOLUMES to 4 in ffconf.h
  • Gone through various fatfs examples in the cube repository to try and see if I'm missing some code (such as 'sd_initialise()' that some seem to use.) No variations have made any difference.
  • #define ENABLE_SD_DMA_CACHE_MAINTENANCE 1

So what could I be doing wrong? has anyone successfully used SDMMC2 with the H7's M4 core? Does cubeMX perhaps not configure the DMA properly?

Any help greatly appreciated.

Many thanks, Matt

9 REPLIES 9

The M4 Core doesn't have a cache, so definitely don't want to be invoking DCache Clean/Invalidate

Top-level FATFS code isn't going to be where the issues are, the DISKIO layer needs to be functional and validated. I'd strongly recommend doing only READs until that is bullet-proof. You really shouldn't need to format cards via MKFS unless you've entirely trashed the FAT Tables and file system structures.

If DMA is used the read/write need to be 32-bit aligned, I'd special case that, or at the very least assert, as most of the interaction you want to be doing is sector aligned and multi-sector if any kind of speed is to be achieved, so interactions at a f_read/f_write level need to be well thought through as there's no meaningful caching or buffering on the media interface side.

Looks like you've got most of the cross connects and stubs dealt with, at least the best you can. I've only used SDMMC1 on these boards. Wire lengths should be short and consistent.

Dial down the slew-rate (SPEED) of the pins, and make sure IO compensation is enabled. At higher speeds (eMMC) I'd probably use 27R or 33R series resistors, but if you're at 6 MHz probably not an issue.

Try 1-bit mode first.

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

Thanks for the reply @Community member​.

  • I have reduced the speed of the clock to ~1.5MHz, and set the GPIO speed to fast, and the edges look good on a scope.
  • I have checked that the data buffer used for a read is 32-bit aligned, which it always is.
  • I have checked that the SDMMC2 ISR is called upon completion of a DMA transfer and that the message is added to the queue, which it is.
  • The problem seems to be that when reading from the SD card, the returned buffer is always full of zeros:

I have attached a screenshot from a logic analyser which shows 2 images. The first is the full transaction when trying to read sector 0, and the second is the same transaction but zoomed in to the start so we can see the data. (sorry, it may be a little hard to read)

It appears that the commands are correct (SEND_STATUS followed by READ_SINGLE_BLOCK) and the card responds, but that the SD card pulls the D0 line low for the entire 512-byte sector read. I'm not 100% sure that's what is happening, but that's what it looks like. I have read the fist sector of the SD card using Hex Workshop on my PC, and it is full of correct looking data.

At first I though there was an issue with the DMA, but now I'm thinking something is causing the card to respond with all zeros.

Again, any help would be greatly appreciated.

Matt

MJack.1
Associate III

Just thought I would add that the D0 line seems to work correctly for other commands - I can see it toggling in the analyser in response to CMD51 (read SCR register).

Does anyone know why the SD card might be responding with all zeros to a read of sector 0?

MJack.1
Associate III

Update - I have tried starting a new project with SDMMC2 on the M7 core and no FreeRTOS, and I get the exact same behaviour. I need to put a delay in the loop that waits for the SD card to reach operating voltage, and sector 0 always reads as blank. I have tried several different SD cards,

Is it possible that the SD card is not actually initialised properly? Is it possible that the master boot record isn't in sector 0?

I could really use some help here please!

MJack.1
Associate III

I'm still stuck on this. I've also roped in another engineer, but we aren't getting anywhere. Any help would be greatly appreciated.

ONadr.1
Senior III

And what about power suply of the card? Is it hard enough? Are there capacitors next by card here? What capacity. You could observe power suply near by card by osciloscope with AC input and high sensitivity. Perharps some power suply glitch reset the card registers.

Thanks for the reply - I do not have any decoupling caps on the supply for the card. There is noise on the supply by the looks of it. I will try to minimise this noise and see if that helps. Thanks for the suggestion

RMora.4
Associate III

I was facing the same trouble with reliably mounting and reading an SD card using SDMMC2 on NUCLEO-L4P5ZG. I tried several things including dialing down the frequency with clock divider, isolating the sd from the rest of circuit, equal wire lengths, ensured correct operating voltage throughout all operations on sd card. My reliability issue still persisted with fatfs returning FR_DISK_ERR, FR_NO_FILESYSTEM, or FR_NOT_READY.

But what is working for me now is using SDMMC1 instead. Not the best answer I know. But if it's possible give that a try. My best guess without exploring further is some conflict with the way the nucleo board uses some of the same default pins that get assigned to SDMMC2 for other purposes.

Thanks for the reply, I forgot to update this post and say that I did get it working in the end.

The SDMMC2 clockDiv was configured to set the clock to 3.75MHz after SD initialisation. I wanted to run it slow to rule out PCB issues. I had to up it to 4MHz and it works reliably now. Perhaps <4MHz is out of some spec I'm not aware of?