cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4 SDMMC standalone mode (no RTOS): Works polled, not with DMA

willcfj
Senior

Hi, pretty sure this is a newbie type question. I'm using the SDMMC interface on an STM32L476. Right now it is just wired to a Nucleo board so I can do some benchmarking before committing it to a layout. I'm using STM32CubeMX and following the example in section 3.3 of UM1721 (Fatfs on CubeMX). After learning the hard way pullup resistors *are* necessary (some other posts said not), I am able to talk to a card, but only if I use polled mode ("Use DMA Template" set to disable in STM32CubeMX Fatfs settings). When enabled, the code hangs in the sd_diskio_dma.c SD_Read() routine right after the BSP_SD_ReadBlocks_DMA() call.

The note for "Use DMA Template" says to ensure that DMAs are properly configured but no more info. In the SDMMC configuration I've tried tried selecting SDMMC1 and then both SDMMC1_TX_SDMMC1_RX. I always get the stall. I am sure there i something basic I'm missing, but been at it for a couple days now and deciding to ask. Since this seems a very basic "follow the app note", rationalizing it might be useful for others too.

I've only recently migrated from the basic StcPeriph libraries to STMCube, starting with the LL routines, this is my attempt using HAL.

will

42 REPLIES 42

I did confirm that the port to the NUCLEO-L452RE was working.

With a 25 MHz clock read of the eMMC was 10.1 MBps, at 50 MHz 17.8 MBps

0690X000006CJAQQA4.jpg

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

Clive:

Good to know, but alas without being able to share your insight on how, not able to learn anything from it.

All:

I have the DMA-driven DAC working fine now, but alas the DMA part was fine, I had a timer misconfigured, so nothing to learn to apply toward SDMMC DMAs.

In thinking about it more, since i am not running an RTOS or anything, even with DMAs running, I am still just sitting in a wait loop for the DMA to finish. I'm not sure getting DMA working will speed things up anyway. I have a few things to wrap up on the DAC side and am going to dig more into exactly what the drivers are doing in non-DMA mode.

will

T J
Lead

Will: you could offer Clive some funding,

I am sure he would share his detailed, difficult, time consuming hard work for some consideration.

I wonder how much time he has spent on your question already ?

Did he make that nucleo board for you ? and write the code and test and confirm the datarates and clock speeds ?

This work is not simple for everyone, I guess Clive has spent 4 hours with you already.

Maybe you could ask in a direct message...

TJ:

My root question is how to get the CubeMX generated code working. Clive's answers are great, just not answering the question I'm asking. I'm in this primarily for education, so not in a position to pay for answers. My reason for posting here is I suspect I'm not the only one having an issue, given I'm just following the app note. My intent is that the final answer (even if ends up coming from me) will be available to anyone with a similar issue able to find this post. That, I believe is the primary purpose of this forum.

I don't begrudge Clive's approach and indeed hope his demonstrated expertise will entice others to contact him for their issues. Both approaches to information sharing are fine, I'm just into the non-paid kind with my few other posts (with answers) following that model.

will

T J
Lead

Hey Will,

I didn't do the SDMMC at this stage, so I am unable to help in this issue...

atcually I did runthe example some years ago, and it worked instantly.. but I never checked the speed..

however,

do you have a scope ? can you see the transactions running across the screen ?

so much easier to debug with a scope, I use the TDS-2024 4 Channel Color, its a little small, but good for this work.

did you find a cube sample for SDMMC ?

most of the examples are in blocking mode, is that what you have ?

I could help maybe restructure your code, if you would like to send it...

willcfj
Senior

TJ:

Given that polled mode works (and works in 4-bit mode too), I've not been looking too much for hardware issues. It would be a bit embarassing (but good) to find out it is a hardware issue of some kind. It is literally just eight wires with 47K pull-up resistors on CMD and the four data lines. No pull-up on CLK. That follows the example I've seen in some demo board schematics. I do have a scope, but just a 2-channel one (Tek TDS-210 60MHz). Signals look pretty good. There is a bit of ringing, but not bad enough to worry about.

The videos suggested by Bojan at the top are good. The link is to 1-bit and the next video is for 4-bit mode. That person strongly suggested downgrading to an older version of CubeMX, but that is a *really* old version now and release notes from ST since then say they fixed the issue he was addressing in the videos. I've started stepping through the code to see where things might not be going right, but DMAs are a bit new to me.

The code snippet is is a cut/paste from the STM32L4 Cube demos (STM32Cube_FW_L4_V1.13.0\Projects\STM32L4R9I-EVAL\Applications\FatFs\FatFs_uSD_DMA_Standalone) pasted into the CubeMX-generated code. and pasted below. Only mods are I commented out formatting step and for f_mount changed the last parameter to actually mount the drive to get the error sooner.

Your queries on it being hardware would make a tidy explanation and bears further study. If ST had an issue and explicitly fixed it, I would suspect it was reasonably well tested. If it were still broken, you think there would be others posting questions too and I couldn't find any.

will

  /*##-0- Turn all LEDs off(red, green, orange and blue) */
      HAL_GPIO_WritePin(GPIOG, (GPIO_PIN_10 | GPIO_PIN_6 | GPIO_PIN_7 |
  GPIO_PIN_12), GPIO_PIN_SET);
  /*##-1- FatFS: Link the SD disk I/O driver ##########*/
  //retSD = FATFS_LinkDriver(&SD_Driver, SD_Path) ; /*  Already called by MX_FATFS_Init.  Calling twice is bad */
      if(retSD == 0){
  /* success: set the orange LED on */
        HAL_GPIO_WritePin(GPIOG, GPIO_PIN_7, GPIO_PIN_RESET);
  /*##-2- Register the file system object to the FatFs module ###*/
    	  res = f_mount(&SDFatFs, (TCHAR const*)SD_Path, 1) ;
          if(res != FR_OK){
       /* FatFs Initialization Error : set the red LED on */
          HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
          while(1);
        }   else    {
  /*##-3- Create a FAT file system (format) on the logical drive#*/
   /* WARNING: Formatting the uSD card will delete all content on the
  device */
    //if(f_mkfs((TCHAR const*)"", 0, 0) != FR_OK){
    //  /* FatFs Format Error : set the red LED on */
    //  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
    //  while(1);
    //} else
  {
  /*##-4- Create & Open a new text file object with write access#*/
    if(f_open(&MyFile, "Hello.txt", FA_CREATE_ALWAYS | FA_WRITE) !=
  FR_OK){
    /* 'Hello.txt' file Open for write Error : set the red LED on */
    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
    while(1);
        } else {
   /*##-5- Write data to the text file ####################*/
     res = f_write(&MyFile, wtext, sizeof(wtext), (void
  *)&byteswritten);
    if((byteswritten == 0) || (res != FR_OK)){
      /* 'Hello.txt' file Write or EOF Error : set the red LED on */
      HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
      while(1);
      } else {
   /*##-6- Successful open/write : set the blue LED on */
      HAL_GPIO_WritePin(GPIOG, GPIO_PIN_12, GPIO_PIN_RESET);
      f_close(&MyFile);
   /*##-7- Open the text file object with read access #*/
      if(f_open(&MyFile, "Hello.txt", FA_READ) != FR_OK){
     /* 'Hello.txt' file Open for read Error : set the red LED on */
      HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
      while(1);
      } else {
   /*##-8- Read data from the text file #########*/
      res = f_read(&MyFile, rtext, sizeof(wtext), &bytesread);
      if((strcmp(rtext,wtext)!=0)|| (res != FR_OK)){
    	  /* 'Hello.txt' file Read or EOF Error : set the red LED on */
    	    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_10, GPIO_PIN_RESET);
    	    while(1);
    	    } else {
    	  /* Successful read : set the green LED On */
    	    HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
    	 /*##-9- Close the open text file ################*/
    	    f_close(&MyFile);
    	  }}}}}}}
    	 /*##-10- Unlink the micro SD disk I/O driver #########*/
    	    FATFS_UnLinkDriver(SD_Path);

T J
Lead

not sure I can help, never used the DMA functionality on SDCards myself.

... but the "Ringing" is showing the ground wire is not up to it.

You code is a bit messy but easy to understand.

You should be able to debug the DMA routines with a Scope. ( 2ch Black&White scope is hard to use.)

Do you know about the holdOff function on the scope, I use that often...

Does the .HEX attached previously function

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

Clive:

OOPS! Not sure how I missed the post with that hex file! Sorry! I just downloaded it and will try it out shortly.

Just to reiterate the point to TJ, I truely hope you understand I'm very OK with your offer of paid help, just not in a position to be paying for help. Hence not bugging you out of respect for your time, not because I am grumpy or anything.

will

willcfj
Senior

TJ:

Since I understand hardware more, I did fiddle with GPIO edge speeds a bit last night first. My clock is a bit slow right now (6MHz), so was able to go all the way down to the "low" IO speed which gave very nice clean edges still much faster than the clock speed. Alas still not working.

On the scope I see activity on all lines and waveforms look good. It follows the expected sequence of activity on the CMD signal, then some activity on data, but comparatively little data on D1-D3 compared to D0. Comms are failing on the first read of sector 0 executing the f_mount command, so comms are failing pretty quickly.

On the code: "Not my fault!" 🙂 That is cut/paste from ST demo code from the path mentioned above the code. I like to feel my code is much cleaner, but right now I just want to minimize variables, so cut/paste of supposedly working code is better than clean untested code.

I also spent a couple hours last night trying to follow the BSP_SD_ReadBlocks_DMA() routine and all of its subroutines, but must admit that I got lost. If the code locked up or threw an error somewhere I'd know where to look. it just all runs fine, but then hangs on the wait after the BSP_SD_ReadBlocks_DMA() routine.

Off to try CLive's code...

will