cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring STM32L431 SDMMC for high speed data transfer using DMA

richard-nuvetech
Associate II

 

Hello everyone,

I have been working with the STM32L431RCTx on a project where I need to log audio data to an SD card. I have attempted to do multiple things unsuccessfully and would really appreciate your help to see where I am going wrong. I am new to working with SD cards, so I recognise that I may have missed something in my research. For all of the below, I have tested with SDHC and SDXC cards with the same results.

First; I have tried to setup the SDMMC interface with at least 20MHz clock speed (clock divide factor 0)

  • The behaviour is very intermittent. It sometimes mounts, opens, writes, closes, then unmounts, but other times will not open or write without an FR_DISK_ERR. My error handling attempts to correct any errors, but I believe there is no fix for a FR_DISK_ERR right? After a while a Hard Fault occurs.
  • I tried again with 40MHz clock speed and clock divide factor of 4. With these settings it goes for longer without errors, however now and then there are still errors that creap in. After a while a Hard Fault occurs too

Second; I have tried to set up 4-bit wide bus communication

  • This failed due to the code getting stuck in a timeout during the SD card initialisation. The timeout value is 0xFFFFFFFF so it is not an infinite loop, but definitely as good as infinite for how long the device will be stuck.

Third; I have tried to enable the DMA transfer using the DMA template in the FatFS settings

  • I won't go into this here (I'll post another question for this later), but at this stage I had no luck with that either. Once I have resolved these other issues I will look more into the DMA. However if any of you know of any resources for using the DMA with the STM32L431, I would really appreciate it. What I did was to enable the DMA template in FatFs, with the DMA settings in SDMMC enabled.

I got it working using 1-bit wide bus, 2MHz clock speed, 0 clock divide factor, FatFs enabled, DMA disabled, SDMMC1 global interrupt enabled.

richardnuvetech_0-1698851652206.pngrichardnuvetech_1-1698851679341.png

richardnuvetech_2-1698851761049.pngrichardnuvetech_3-1698851800081.pngrichardnuvetech_4-1698851903952.png

The Detect_SDIO pin is selected (in this case input on PC6)

Using this configuration I can read, write, and format etc. However if I try to keep the settings the same, while increasing the speed above 2MHz; or changing the bus width to 4-bit, I get the errors described above. This seems to be the only stable combination of settings. This is unfortunately way too slow for my application, considering that I believe it should be able to operate at 32MHz, 4-bit wide bus; that would mean a 64 times increase in speed from 2MHz 1-bit wide bus.

I have attached my slow but working configuration code below. My system clock speed is 20MHz, derived from an 8MHz crystal.

I would really appreciate any assistance. If you notice any fundamental flaws in my understanding of working with SD card I'd welcome the feedback. Thank you in advance.

6 REPLIES 6
elso
Associate III

Hi,

What type of SD card do you use? (Class and model)

If not too sensitive, can you send a picture of your SD card module and setup?

(I am using a STM32H723ZG with a class 10 SD card using 96MHz clock with clock divide factor of 4, no gpio pull-up and pull-down).

Can you send a picture of your FATFS --> platform settings?

Maybe this "hack" can fix your 4-bit code setup from failing (did for me):

static void MX_SDMMC1_SD_Init(void)
{
  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; //Setting in 1 bit mode.
  hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd1.Init.ClockDiv = 4;
HAL_SD_DeInit(&hsd1); //For re-initialization
if (HAL_SD_Init(&hsd1) != HAL_OK)
  {
	  Error_Handler();
  }
  if (HAL_SD_ConfigWideBusOperation(&hsd1, SDMMC_BUS_WIDE_4B) != HAL_OK) //setting it to 4 bit mode.
  {
	  Error_Handler();
  }
}

 

richard-nuvetech
Associate II

Hi elso,

Thank you for the reply. The cards I have tried are the following:

  • SanDisk SDHC 4GB Speed Class 4
  • Netac microSD SDHC 8GB Speed Class 10
  • Patriot microSD SDXC 64GB Speed Class 10, UHS Speed class 3, Video Speed class 30

20231107_081622.jpg

Here are the pictures of the device and SD card schematic:

richardnuvetech_0-1699337539395.png

20231107_080752.jpg

This board is a 2-tier with the SD card directly above the microcontroller (STM32L431) beneath, with the signals going through pin headers. Trace (and pin) distance for signals to travel is about 5cm.

Another board I have tried, which has the same schematic for the SD card, is a single PCB (not a 2-tiered PCB as shown above), however the distance was about 15cm between the SD card and the micro (STM32L431) which I feel is adding problems to signal integrity.

 

Here are my FATFS platform settings and advanced settings:

richardnuvetech_1-1699338775482.pngrichardnuvetech_2-1699338806208.png

 

I tried your "Hack" for fixing the 4-bit wide bus, but I don't think it actually fixes it. I don't get an error anymore, but when I use an oscilloscope to check the lines, the only signals I see are on CMD, CLK, and D0. D1-3 remain high. Do you see signals on your side for D1-3?

 

AScha.3
Chief III

at first, set / use 1-bit mode only; (4 bit mode is more challenging with regard to signal quality )

find stable working setting then. (set pin speed medium or medium-high , not highest! , and pullups on.)

clk should work at 50M. ( i have 100MHz and div1 , so sd-card can work at highest possible speed - depending on card ! )

use "good" sd-card (SanDisk, Samsung), and only read ! never write or mkfs format , before read perfect working.

maybe set fatfs to read-only at first, to avoid destroy cards...

btw

i had no luck with "dma template", so i never use dma here ; anyway useless, if i/you want to read or write on card and wait for finishing this - useless to have dma , if cpu fast enough for transfer at max speed.

If you feel a post has answered your question, please click "Accept as Solution".

Hi Richard,

I got this "hack" from another post purposed by an ST employee, so if it doesn't work, I would need to look into it myself. I have not checked the pins, but I would assume I would have the same problems as you! I will keep you updated if I find a solution :)

Hi AScha.3

I will try using your suggestions, and see how they go.

I reworked my code to do only the bare bones mount, open, write, close, unmount. Repeating that over and over again. Doing this I found that it only gives errors on closing, but it recovers from the FR_DISK_ERR when the process starts again. So I will see about adding the mount and open as recover methods after the error occurs.

I did decrease the pin speed and it seemed to make a slight improvement, but it still fails to close the SD card at times with an FR_DISK_ERR. I can now operate at 40MHz with 4 clock divide factor and it only fails once every 5-10 times. Definitely something that can improve, but there is progress.

The new code is:

 

void testSD() {
	FRESULT res3 = FR_OK;
	res3 = f_mount(&myFatFS, (TCHAR const*) SD_Path, 1);
	if (res3 == FR_OK) { //mount
//		printf("mount success\n");
		res3 = f_open(&myFile, "TEST2.WAV", SD_Append);
		if (res3 == FR_OK) { //open
//			printf("open success\n");
			char temp[16] = {'\0'};
			memset(temp,'_',15);
			temp[16] = '\n';
			sprintf(temp,"%d",HAL_GetTick());
			res3 = f_write(&myFile, temp, 16, (void*) &byteswritten);
			if (res3 == FR_OK) { //write
//				printf("write success\n");
				res3 = f_sync(&myFile);
				if (res3 == FR_OK) { //close
//					printf("close success\n");
					res3 = f_mount(NULL, (TCHAR const*) SD_Path, 1);
					if (res3 == FR_OK) { //unmount
						printf("Full success\n");

					} else
						printf("unmount fail %d\n",res3);
				} else
					printf("close fail %d\n",res3);
			} else
				printf("write fail %d\n",res3);
		} else
			printf("open fail %d\n",res3);
	} else
		printf("mount fail %d\n",res3);
}

 

 

on H563 Cube force speed high + no pullup : -> sd never working.

i overwrite setting in ..hal_msp.c : to medium + pullup :

AScha3_0-1699631658461.png

then sd working fine , with ~ 10 cm flat ribbon wire to sd card holder ! at 100MHz /div1 = 50M clk.

if you have wires, keep them together, both gnd on separate wires connected, and a cer cap at the card holder.

 

If you feel a post has answered your question, please click "Accept as Solution".