2018-03-04 08:51 PM
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.
2018-03-07 10:20 AM
,
,
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.cFATFS 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
2018-03-07 10:29 AM
Goosing the SDCLK higher for the U1 card
Core=200000000, 200 MHz
CPUID 410FC271 DEVID 449 REVID 1001Cortex M7 r0p1STM32F74xxx or F75xxxC0000000 FFFFFFF8 0000000010110021 11000011 00000040FPU-S Single-precision onlyAPB1=50000000APB2=100000000Display 480 x 272FatFs Testing (68300)EXFAT 192.2 GB total drive space 192.2 GB available 32.5 MB used---- 32768000 /SPEEDTST.BINCRC32 65744B39 Memory Image32768000 Bytes, 467262118 Cycles 14.03 MBps Write (FatFs) 2336 ms 14.03 MBps SysTick Sanity20008890 4096CrcFile Size:32768000 BufferSize:4096 32768000 CRC32:65744B39 PKZIP:9A8BB4C6 SPEEDTST.001 6.23 MBps Crc (FatFs) 5257 ms 6.23 MBps SysTick Sanity32768000 Bytes, 466515834 Cycles 14.05 MBps Write (FatFs) 2333 ms 14.05 MBps SysTick Sanity20008890 4096CrcFile Size:32768000 BufferSize:4096 32768000 CRC32:65744B39 PKZIP:9A8BB4C6 SPEEDTST.001 6.23 MBps Crc (FatFs) 5258 ms 6.23 MBps SysTick Sanity32768000 Bytes, 326643971 Cycles 20.06 MBps Read (FatFs) 1633 ms 20.07 MBps SysTick Sanity32768000 Bytes, 326651548 Cycles 20.06 MBps Read (FatFs) 1634 ms 20.05 MBps SysTick SanityDone.PLL P:200000000 Q:100000000 R:200000000PLLI2S P: 96000000 Q: 96000000 R: 96000000PLLSAI P: 48000000 Q: 96000000 R: 38400000PLL48CLK 100000000, 100.00 MHzSDCLK 50000000, 50.00 MHzLCDCLK 9600000, 9.60 MHzInfinite loop...2018-03-07 10:46 PM
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';
2018-03-08 01:02 AM
which NVIC / DMA did you select?
SDMMC 1 and two DMA Channels for RX / TX
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.
2018-03-08 09:01 AM
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.
2018-03-08 09:06 AM
Sorry forgot to add, the file name is now appearing on the SD card with no data in the file.
2018-03-08 10:21 AM
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.
2018-03-08 10:59 AM
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
2018-03-08 11:18 AM
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.
2018-03-08 12:34 PM
,
,
♯ 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,,
}