2025-10-08 2:03 PM
HI,
I need help because I'm going crazy.
I’m trying to use SD card with STM32H747 on the M4 core using FatFS and SDMMC1 and FreeRTOS, but the MDMA write never completes and the write complete callback is never called. This happens when I try to format the SD card with f_mkfs, f_mkfs calls SD_write, which eventually triggers HAL_SD_WriteBlocks_DMA. and in which i it crashes. Reading works OK problem occurs only in writing. Tested on many SD cards.
Here’s a snippet of SD_write function with debug:
uint8_t res;
printf("[SD_write] Starting DMA write: %lu blocks to sector %lu...\n", count, sector);
res = BSP_SD_WriteBlocks_DMA((uint32_t*)buff, sector, count);
if (res == MSD_OK) {
printf("[SD_write] DMA write started OK. Waiting for queue event...\n");
#if (osCMSIS < 0x20000U)
event = osMessageGet(SDQueueID, SD_TIMEOUT);
if (event.status == osEventMessage && event.value.v == WRITE_CPLT_MSG) {
printf("[SD_write] Write complete received\n");
}
#else
status = osMessageQueueGet(SDQueueID, (void *)&event, NULL, SD_TIMEOUT);
if ((status == osOK) && (event == WRITE_CPLT_MSG)) {
printf("[SD_write] Write complete received\n");
}
#endif
} else {
printf("[SD_write] BSP_SD_WriteBlocks_DMA returned error\n");
}
And my BSP function:
__weak uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{
uint8_t sd_state = MSD_OK;
printf("[BSP_SD_WriteBlocks_DMA] Start: pData=%p, WriteAddr=%lu, NumOfBlocks=%lu\n",
(void*)pData, (unsigned long)WriteAddr, (unsigned long)NumOfBlocks);
if (HAL_SD_WriteBlocks_DMA(&hsd1, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK)
{
sd_state = MSD_ERROR;
printf("[BSP_SD_WriteBlocks_DMA] HAL_SD_WriteBlocks_DMA returned error!\n");
} else {
printf("[BSP_SD_WriteBlocks_DMA] HAL_SD_WriteBlocks_DMA started successfully\n");
}
return sd_state;
}
i also turned on
#define USE_HAL_SD_REGISTER_CALLBACKS 1U /* SD register callback disabled */
in stm32h7xx_hal_conf.h
and
hsd1.TxCpltCallback = BSP_SD_WriteCpltCallback;
in sdmmc.c
but
void BSP_SD_WriteCpltCallback(void)
{
/*
* No need to add an "osKernelRunning()" check here, as the SD_initialize()
* is always called before any SD_Read()/SD_Write() call
*/
#if (osCMSIS < 0x20000U)
("[BSP_SD_WriteCpltCallback] osCMSIS < 0x20000U \n");
osMessagePut(SDQueueID, WRITE_CPLT_MSG, 0);
#else
("[BSP_SD_WriteCpltCallback] else\n");
const uint16_t msg = WRITE_CPLT_MSG;
osMessageQueuePut(SDQueueID, (const void *)&msg, 0, 0);
#endif
}
in sd_diskio.c is never called!!!
and the output:
[SD_write] Start: sector=63, count=1, buff=0x10000260
[SD_write] Starting DMA write: 1 blocks to sector 63...
[BSP_SD_WriteBlocks_DMA] Start: pData=0x10000260, WriteAddr=63, NumOfBlocks=1
[SD_write] SDMMC1_IRQHandler
[HAL_SD_IRQHandler] Context=0x00000090 State=3 Err=0x00000000
[HAL_SD_IRQHandler] FLAGS: DATAEND=0 IDMABTC=0 TXFIFOHE=0 RXFIFOHF=0 DCRCFAIL=0 DTIMEOUT=0 RXOVERR=0 TXUNDERR=1
[BSP_SD_WriteBlocks_DMA] HAL_SD_WriteBlocks_DMA started successfully
[SD_write] DMA write started OK. Waiting for queue event...
[SD_write] No valid write complete message in queue
other config below:
__attribute__((section(".RAM_SHARED"))) uint8_t wtext[] = "STM32 FATFS works great!"; /* File write buffer */
__attribute__((section(".RAM_SHARED"))) uint8_t rtext[_MAX_SS];/* File read buffer */
printf("sd INT STARTED\r\n");
#if (osCMSIS > 0x20000U)
printf("Kernel state = %d\n", osKernelGetState());
#else
printf("Kernel running = %d\n", osKernelRunning());
#endif
if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
{
printf("f_mount error!\r\n");
Error_Handler();
}
else
{
FRESULT res = f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, rtext, sizeof(rtext));
if(res != FR_OK)
{
uint8_t sd_status = BSP_SD_IsDetected();
if(sd_status == SD_PRESENT)
{
printf("SD card is present.\n");
}
else
{
printf("SD card is NOT present!\n");
// Tutaj możesz przerwać inicjalizację FS, bo nie ma karty
}
DSTATUS stat = disk_initialize(0);
printf("disk_initialize returned 0x%02X\n", stat);
printf("f_mkfs error!\r\n");
printf("f_mkfs failed! Error code = %d: ", res );
switch(res)
{
case FR_OK: printf("Succeeded\n"); break;
case FR_DISK_ERR: printf("A hard error occurred in the low level disk I/O layer\n"); break;
case FR_INT_ERR: printf("Assertion failed\n"); break;
case FR_NOT_READY: printf("The physical drive cannot work\n"); break;
case FR_NO_FILE: printf("Could not find the file\n"); break;
case FR_NO_PATH: printf("Could not find the path\n"); break;
case FR_INVALID_NAME: printf("The path name format is invalid\n"); break;
case FR_DENIED: printf("Access denied due to prohibited access or directory full\n"); break;
case FR_EXIST: printf("Access denied due to prohibited access\n"); break;
case FR_INVALID_OBJECT: printf("The file/directory object is invalid\n"); break;
case FR_WRITE_PROTECTED: printf("The physical drive is write protected\n"); break;
case FR_INVALID_DRIVE: printf("The logical drive number is invalid\n"); break;
case FR_NOT_ENABLED: printf("The volume has no work area\n"); break;
case FR_NO_FILESYSTEM: printf("There is no valid FAT volume\n"); break;
case FR_MKFS_ABORTED: printf("f_mkfs() aborted due to any problem\n"); break;
case FR_TIMEOUT: printf("Could not get a grant to access the volume within defined period\n"); break;
case FR_LOCKED: printf("The operation is rejected according to the file sharing policy\n"); break;
case FR_NOT_ENOUGH_CORE: printf("LFN working buffer could not be allocated\n"); break;
case FR_TOO_MANY_OPEN_FILES: printf("Number of open files > _FS_LOCK\n"); break;
case FR_INVALID_PARAMETER: printf("Given parameter is invalid\n"); break;
default: printf("Unknown error\n"); break;
}
// Error_Handler();
}
else