cancel
Showing results for 
Search instead for 
Did you mean: 

Why can I not get past f_open with SD card

GreenGuy
Lead
Posted on March 05, 2018 at 05:51

I am working with STM32F746G-Disco board to prove out the use of the SD card.  I am at a point where I cannot get the code to write data to the card using the fs calls.  First, I have setup the board in CubeMX with all the peripherals for the disco board initialized although I am only working with the FATfs, SD card and the screen for debug. The Cube project file is attached.  The code is working up to the point where f_open is called but f_open does not seem to return.  The code looks like this:

  /* USER CODE BEGIN 5 */

  sdres = BSP_SD_Init();

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 94, (uint8_t *)'SD Init status Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 94, (uint8_t *)'SD Init status Fail', LEFT_MODE);

  sdres = f_mount(&sdFatfs, '', 0);

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD mount Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD mount Failed', LEFT_MODE);

  sdres = f_open(&sdFile, 'test.txt', FA_OPEN_ALWAYS|FA_WRITE|FA_READ);

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD open Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD open Failed', LEFT_MODE);

  sdres = f_lseek(&sdFile, sizeof(&sdFile));

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD seek Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD seek Failed', LEFT_MODE);

  sdres = f_printf(&sdFile, '%s', buffSDwr);

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD print Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD print Failed', LEFT_MODE);

  sdres = f_close(&sdFile);

  if (sdres == FR_OK) BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD close Pass', LEFT_MODE);

  else BSP_LCD_DisplayStringAt(0, 124, (uint8_t *)'SD close Failed', LEFT_MODE);

The sdFile, sdFatfs, sdres, and buff... variables are all global to main.c being declared in the USER PV area.

When this runs, the LCD screen prints

SD Init status Pass

SD mount Pass

after which nothing else appears.  It is also interesting to note that if I set break points at the f_open call and just after the call, the debugger stops at f_open but when I click run to go to the next break point the execution pointer simply stops at the f_open call again.  ODD!  If i place the cursor a couple of lines down and select run to cursor, the same thing happens.  If I try to step over the f_open line the debugger ends up at the first instruction in the tick handler.  I have exhausted all the posts, youtube tutorials, and blogs and nothing has settled the issue.

31 REPLIES 31
Posted on March 07, 2018 at 18:20

 ,

 ,

I have examples built under the HAL trees from the STM32F746G-DISCO supporting DMA and POLLED operation.

I derived this from

Repository\STM32Cube_FW_F7_V1.9.0\Projects\STM32746G-Discovery\Applications\Display\LTDC_PicturesFromSDCard

// DMA from STM32Cube_FW_F7_V1.9.0\Projects\STM32756G_EVAL\Applications\USB_Host\

 ,

// , , DynamicSwitch_Standalone\Src\sd_diskio_dma.c

FATFS SDFatFs, , /* File system object for SD card logical drive */

 ,

char SDPath[4], /* SD card logical drive path */

...

 , BSP_SD_Init(),

 , while(BSP_SD_IsDetected() != SD_PRESENT)

 , {

 ,

 , , , BSP_LCD_SetTextColor(LCD_COLOR_RED),

 ,

 , , , BSP_LCD_DisplayStringAtLine(8, (uint8_t*)' , Please insert SD Card , , , , , , , , , , , , , , , , , '),

 ,

 , }

...

 , /* ♯ ♯ -2- Link the SD Card disk I/O driver ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ */

 ,

 , if (FATFS_LinkDriver(&,SD_Driver, SDPath) == 0)

 ,

 , {

 ,

 , , , /* ♯ ♯ -4- Register the file system object to the FatFs module ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ ♯ */

 ,

 , , , if (f_mount(&,SDFatFs, (TCHAR const*)SDPath, 0) == FR_OK)

 ,

 , , , {

 ,

 , ,  , , ,  , , ,  ,FATTest(),

 ,

 , ,  , , ,  ,}

 ,

 , }

 ,

 , else

 ,

 , {

 ,

 , , , /* FatFs Initialization Error */

 ,

 , , , Error_Handler(),

 ,

 , }

With the SDMMC clock running at 50 MHz (25 MHz 4-bit to the card), I'm seeing 10.75 MBps read onto a generic SanDisk 16GB microSDHD, and 10.98 onto an EXFAT 200GB SanDisk Ultra Plus.

I also have builds working on the STM32F769I-DISCO which uses SDMMC2 and DSI. The LCD clock there is north of 27 MHz depending on the LCD vs HDMI, compared to 9.6 MHz for the 746G

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 07, 2018 at 18:29

Goosing the SDCLK higher for the U1 card

Core=200000000, 200 MHz

CPUID 410FC271 DEVID 449 REVID 1001

Cortex M7 r0p1

STM32F74xxx or F75xxx

C0000000 FFFFFFF8 00000000

10110021 11000011 00000040

FPU-S Single-precision only

APB1=50000000

APB2=100000000

Display 480 x 272

FatFs Testing (68300)

EXFAT

  192.2 GB total drive space

  192.2 GB available

   32.5 MB used

----   32768000 /SPEEDTST.BIN

CRC32 65744B39 Memory Image

32768000 Bytes, 467262118 Cycles

 14.03 MBps Write (FatFs)

  2336 ms

 14.03 MBps SysTick Sanity

20008890 4096

CrcFile Size:32768000 BufferSize:4096

  32768000 CRC32:65744B39 PKZIP:9A8BB4C6 SPEEDTST.001

  6.23 MBps Crc   (FatFs)

  5257 ms

  6.23 MBps SysTick Sanity

32768000 Bytes, 466515834 Cycles

 14.05 MBps Write (FatFs)

  2333 ms

 14.05 MBps SysTick Sanity

20008890 4096

CrcFile Size:32768000 BufferSize:4096

  32768000 CRC32:65744B39 PKZIP:9A8BB4C6 SPEEDTST.001

  6.23 MBps Crc   (FatFs)

  5258 ms

  6.23 MBps SysTick Sanity

32768000 Bytes, 326643971 Cycles

 20.06 MBps Read  (FatFs)

  1633 ms

 20.07 MBps SysTick Sanity

32768000 Bytes, 326651548 Cycles

 20.06 MBps Read  (FatFs)

  1634 ms

 20.05 MBps SysTick Sanity

Done.

PLL    P:200000000 Q:100000000 R:200000000

PLLI2S P: 96000000 Q: 96000000 R: 96000000

PLLSAI P: 48000000 Q: 96000000 R: 38400000

PLL48CLK 100000000, 100.00 MHz

SDCLK     50000000,  50.00 MHz

LCDCLK     9600000,   9.60 MHz

Infinite loop...
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
GreenGuy
Lead
Posted on March 08, 2018 at 07:46

OK, finally made it past f_open.  this is what I did.

In Cube MX Configuration:

1. In DMA, in the DMA2 tab, under DMA Request, use select box to pick SDMMC1.

2. in the NVIC, you should see the interrupt checked for DMA2, but also make sure the interrupt is checked for SDMMC1.

f_open now works.  f_printf fails and takes a really long time (~20s) to do so after writing a small test string.

sdres = f_printf(&MyFile, '%s', wtext)

where wtext is defined as:

uint8_t wtext[] = 'This is STM32 working with FatFs';

feuerwolf
Senior
Posted on March 08, 2018 at 10:02

which NVIC / DMA did you select?

SDMMC 1 and two DMA Channels for RX / TX

0690X00000604PQQAY.jpg

The core problem is, that the SDMMC_Data_send/Receive_DMA RX/TX Interrupt does not fire by plain Cube created code. So the DMA interrupt has to be started before, maybe by put it in circular mode and fill the IRQHandler....

I see that :

void SDMMC1_IRQHandler(void) gets called,

HAL_SD_RxCpltCallback         gets called,

but

HAL_SD_TxCpltCallback does not get called

I am  currently reading myself into DMA topic to understand the process completely. So i Think the generated Code is fine, there just has to be added a few lines in order to let the DMA interrupts fire.

GreenGuy
Lead
Posted on March 08, 2018 at 18:01

Sorry, the website is not taking my snips so I will have to describe what I see in CubeMX.

SDMMC1 Configuration:

1. NVIC Settings: I show in the interrupt table SDMM1C global interrupt Enabled

    and DMA2 stream3 global interrupt enabled

2. DMA Settings: I show SDMMC1 under DMA Request, DMA2 Stream 3 under Stream, Peripheral to Memory under Direction, and Priority Low.

DMA Configuration:

1. DMA2: is the same info as DMA Settings from the SDMMC1 configuration window.

I notice that the TX and RX options in the DMA Configuration showed RX and TX options in red.  So I deleted the DMA2 selection and went back to the SDMMC1 settings.  There under DMA Settings I added the SDMMC1_RX and TX streams.

The FRESULT is 35 which I am not sure what that means.  However the  f_printf function returns immediately and now the f_close function takes about 15 seconds to complete and returns with FR_DISK_ERR.

GreenGuy
Lead
Posted on March 08, 2018 at 18:06

Sorry forgot to add, the file name is now appearing on the SD card with no data in the file.

GreenGuy
Lead
Posted on March 08, 2018 at 19:21

I was lead to believe (do not know from where) that f_printf returns an FR Status.  It is actually returning the number of bytes written.

Posted on March 08, 2018 at 18:59

I was digging through the L4 code Elkin's posted

https://community.st.com/0D50X00009XkiYhSAJ

last night.

Have that building on Keil, I can't really see where the code initiates DMA transfers, there's a whole rats nest of code additions related to the L4Rx series parts, where DMA does work. The only place I'm seeing DMA code is on the abort paths, which is too after the fact to be of any use. Basically it looked like the DMA didn't get initiated, thus no IRQ to indicate it finished.

Got the code working with Polled mode, and used SWV debug output so I could see what was happening.

The example code in the HAL F7 trees is viable in Polled or DMA operation for the most part, I try to keep transfers in the DTCM to avoid caching woes. Some disconnected defines on the F769I-DISCO

https://community.st.com/0D50X00009XkgXcSAJ

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
GreenGuy
Lead
Posted on March 08, 2018 at 20:18

I have traced down to the problem.  When f_close is called, the function SD_write gets called to flush the cache finishing any remaining writes that need to occur.  In SD_write, BSP_Writeblocks_DMA gets called which returns an MSD_OK status.  Then a Global variable WriteStatus is checked indicating the write has completed but it never gets set to 1 so a timeout period elapses.  The WriteStatus variable is set to 1 by the callback BSP_SD_WriteCpltCallback.  I can not see anywhere in the code generated by CubeMX that BSP_SD_WriteCpltCallback is referenced so it can respond to the TX DMA interrupt.

Posted on March 08, 2018 at 20:34

 ,

 ,

♯ define BSP_SDMMC_DMA_Tx_IRQHandler , , , , , , DMA2_Stream6_IRQHandler

..

stm32f7xx_it.c

void BSP_SDMMC_DMA_Tx_IRQHandler(void)

 ,

{

 ,

 , HAL_DMA_IRQHandler(uSdHandle.hdmatx),

 ,

}

..

stm32f7xx_hal_sd.c, likely via HAL_SD_IRQHandler(&,uSdHandle), as FIFO flushes across SDMMC

..

stm32746g_discovery_sd.c

void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)

 ,

{

 ,

 , BSP_SD_WriteCpltCallback(),

 ,

}

..

sd_diskio.c

void BSP_SD_WriteCpltCallback(void)

 ,

{

 ,

 , WriteStatus = 1,

 ,

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