cancel
Showing results for 
Search instead for 
Did you mean: 

SD (read-only) memory leaks issue

jean
Senior

Hi, I hope you are well!

I get stuck on the same issue since a few months:

I stream multiple audio files (.wav), at the same time and continuously. After 24 hours of streaming, SD card files start to be corrupted (data is wrong) and when I inspect the free memory space on my computer, it says about 10GB is remaining (instead of the initial 15GB free memory). After 48H of streaming, free memory goes down to about 5GB. This is why I guess that my STM32F722 write something on the SD card, even if I disabled all WRITE features.

I have this issue with:

* SD card are freshly formatted with the official SD card software

* 3 other different SD cards

* different system clock configurations

* different FatFs configurations

* different InitSDCard configurations

* SD DMA enable or disable

* last FatFs and last HAL SD driver

Also, I think my PCB is good, as I followed the important design guidelines (length matching, ground plane, 10cm tracks). The average speed is quite good to me: 5Mo/s, and reading blocs (1024bytes per 1024bytes of a file) never fail.

Do you have any idea of why this issue happen? Is this a known driver problem? I have the feel I already tested all the combinations of parameters. Any ideas are welcome!

Cheers,

8 REPLIES 8

Not aware of conditions where it would write in read only applications.

Instrument the write functionality in DISKIO

The FatFs provided by ST is a few years old.1​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jean
Senior
  SCB_EnableICache();
  SCB_EnableDCache();
 
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 216;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) __DEBUG_BKPT();
 
  if (HAL_PWREx_EnableOverDrive() != HAL_OK) __DEBUG_BKPT();
  
  /* Initializes the CPU, AHB and APB busses clocks */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) __DEBUG_BKPT();
 
  /* USART + SD CLOCK */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_SDMMC1|RCC_PERIPHCLK_CLK48;
  PeriphClkInitStruct.PLLSAI.PLLSAIN = 96;
  PeriphClkInitStruct.PLLSAI.PLLSAIQ = 2;
  PeriphClkInitStruct.PLLSAI.PLLSAIP = RCC_PLLSAIP_DIV4;
  PeriphClkInitStruct.PLLSAIDivQ = 1;
  PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_2;
  PeriphClkInitStruct.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInitStruct.Clk48ClockSelection = RCC_CLK48SOURCE_PLLSAIP; 
  PeriphClkInitStruct.Sdmmc1ClockSelection = RCC_SDMMC1CLKSOURCE_CLK48; 
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) __DEBUG_BKPT();
  hsd1->Instance = SDMMC1;
  hsd1->Init.ClockEdge = SDMMC_CLOCK_EDGE_FALLING;
  hsd1->Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
  hsd1->Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_ENABLE;
  hsd1->Init.BusWide = SDMMC_BUS_WIDE_1B;
  hsd1->Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE;
  hsd1->Init.ClockDiv = speed;

    // SDMMC1 no-DMA version
    __HAL_RCC_SDMMC1_CLK_ENABLE();
 
    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_2; //CMD
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

jean
Senior

Thanks @Community member​ ,

  • Even if I comment SD_write() inside DISKIO, the problem still appears...
  • I use the "official" FatFs R0.14 from http://elm-chan.org/, not the one from ST

But does it ever use the function?​

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

No, added a breakpoint but it never enter SD_write

Having run such systems for months on end, and writing, without trashing my cards, I'm going to assume there is some other issue at play.

Make sure the stack is adequate, and that you aren't corrupting internal memory/structures.

Add sanity checking so you can immediately sense/determine failure.

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

Thanks, it's a good news if it can run for month!

1) how can I make sure that the stack is adequate? Do you recommend a value?

2) I seems difficult for me to know when a corruption happen, as my files are read and played normally, with no error returned from drivers. But the data read is wrong, looking random... Also, the corruption "sector" looks random, sometimes the end of a file is corrupted, sometime the beginning of a file I never opened is corrupted, sometimes a folder is corrupted and looks like a file, ...

The thing that is unexplicable for me is, how can the driver write and add/replace data if I'm using only read functions?

Not sure what tools you're using, but Keil by default has a very small stack this usually can't hold a sector of data, or have printf/scanf function properly.

Start with a couple of KB, and make a determination about how much your application normally uses over time, and perhaps review static analysis of call-tree output by the linker. The stack is like other memory, you can inspect it, and fill it with a pattern so you can observe the deepest point. Add some margin to that, and consider your use of auto/local variables, and which functions my be called under interrupt or nest.

If it is not a software stack issue, then communication could be a problem, and the card may be misinterpreting a command or sequence. Check power and termination. Replicate failure on ST EVAL/DISCO boards.

>>The thing that is unexplicable for me is, how can the driver write and add/replace data if I'm using only read functions?

Yes, you're skirting the edge of the known universe here. You might need to get a logic/bus analyzer to see what's happening if you can rule out all software side issues. Not seeing reports of this type of failure.

Get a card filed with 100's GB of test pattern files (Pseudo-Range, LFSR type stuff), so you can soak test the reading of data until you observe failure. Trying to observe minimum time to failure, and a means to trigger analyzers or time stamp failure to review captures/logs.

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