cancel
Showing results for 
Search instead for 
Did you mean: 

I have a problem in FatFS f_write gives FR_DISK_ERR & FR_INVALID_OBJECT

AAl-H
Associate III

Hello,

I'm sorry if this is the wrong section

I'm using STM32CubeMX on custom STM32F407VG

I'm using 1-Bit mode SD card with FatFS middleware (4-Bit didn't work at all)

I'm writing 500-1000 bytes to a txt file every ~30ms

Once the file size is > 2MB I close it and open another txt file

It works fine for few minutes and creates multiple files as well, but sometimes the f_write fails giving a FR_DISK_ERR, when I try to close it it'll give the same error

When I try to write or close again after the previous error it'll give FR_INVALID_OBJECT

Once I see this error only a HW reset of the MCU will solve it

I tried deinit/init of the HAL_SD or FatFS but nothing worked

Attached the code I'm using, this function is currently called every ~100ms with these problems, but the goal is to call it every ~30ms

void PIR_to_SD(char myData[]){
	uint8_t status = FR_OK;
//mount SD if it's not already mounted
	if(!sd_mount){
		status = f_mount(&myFATAFS, SDPath, 0);
		if(status != FR_OK){
			printf("SD: Failed to mount, status = %d\r\n", status);
			return;
		}
		sd_mount = 1;
	}
//create new file if the previous file is closed
	if(new_file){
		sprintf(fileName, "%s%d%s", myPath, f_number++, format);
		printf("filename: %s\r\n", fileName);
		status = f_open(&myFILE, fileName, FA_READ | FA_WRITE | FA_OPEN_APPEND);
		if(status != FR_OK){
			printf("SD: Failed to open file, status = %d\r\n", status);
			return;
		}
		new_file = 0;
	}
//write data if file is successfully opened
	if(write_flag){
		status = f_write(&myFILE, myData, strlen(myData), &testByte);
		if(status != FR_OK){
			printf("SD: Failed to write data, status = %d\r\n", status);
//			write_flag = 0;
		}
	}
//close file if size>2MB OR f_write had an error
	if(f_size(&myFILE) > 2000000 || status != FR_OK || !write_flag){
		status = f_close(&myFILE);
		if(status != FR_OK){
			printf("SD: Failed to close file, status = %d\r\n", status);
		}
		else{
			write_flag = 1;
			new_file = 1;
		}
	}
//none of these worked to solve the problem
/*
	if(status != FR_OK){
		status = f_mount(0, SDPath, 0);
		printf("SD: unmount, status = %d\r\n", status);
		sd_mount = 0;
		printf("unlink = %d\r\n", FATFS_UnLinkDriver(SDPath));
		printf("SD: deinit = %d\r\n", HAL_SD_DeInit(&hsd));
//PD3 is power enable for the SD
		HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_3);
		HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_3);
		printf("SD: init = %d\r\n", HAL_SD_Init(&hsd));
		MX_FATFS_Init();
	}
*/
}

3 REPLIES 3
AAl-H
Associate III

I'm going to write what I found in case someone in the future has the same problem

The problem happens in this function: HAL_SD_WriteBlocks that is being called by FatFS

It gets stuck in a loop till it timeout (Important notice: the default timeout of the caller (FatFs) is very long so be careful if you're using watchdog)

I still didn't know what is the cause of the problem but the way to recover from it:

If f_write returns FR_DISK_ERR call HAL_SD_InitCard function and then f_close the file. However, you'll lose the last 1-2 packets you tried to write to the file

This will make it recover from the error

I still don't know why the error happens in the first place

RViei.2
Associate

Hi,

I don't know if you solved this, but I faced a similar problem. To work in 4-bit mode you need to decrease the the SDIOCLK, normally 12MHz is ok, in my case this start to work whit 9MHz, but I still goted some errors. With 4,5Mhz I didn't have any more problems

In my case (HCLK = 72MHz and ABP2 = 72MHz) I put SDIOCLK DIV = 14:

SDIOCLK = APB2 / (SDIOCLK DIV + 2)

static void MX_SDIO_SD_Init(void)
{
 
  /* USER CODE BEGIN SDIO_Init 0 */
	DEBUG_INIT("Func %s at %s, line %dc\n\r", __FUNCTION__, __FILE__, __LINE__);
 
  /* USER CODE END SDIO_Init 0 */
 
  /* USER CODE BEGIN SDIO_Init 1 */
 
  /* USER CODE END SDIO_Init 1 */
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 13;
  /* USER CODE BEGIN SDIO_Init 2 */
  if(HAL_SD_Init(&hsd) != HAL_OK)
  {
	  Error_Handler();
  }
  if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
  {
	  Error_Handler();
  }
  /* USER CODE END SDIO_Init 2 */
 
}

Thank you for your reply

No, we didn't work it out and we've been using 1-bit mode since

I'm going to try your solution later and see if it fixes the problem