cancel
Showing results for 
Search instead for 
Did you mean: 

Why does FatFS work sometimes, and sometimes not?

DMÃ¥rt
Lead

Hi!

I'm using FatFS R0.11 with STM32F373 and sometimes it works to use FATFS and sometimes not.

These are the issues I got and I don't know why.

Can it be something with NVIC interrupts that causing issues with the FatFS library?

Mount SD card:

Mount SD card -> Unmount SD card -> Unplug SD card -> Insert SD card -> Mount SD card. This will create an error for me. I cannot unmount the SD card and unplug it and then insert it back again and mount it. I get a FR_DISK_ERR then.

Notice if I re-flash the STM32 processor or go into debugging mode, then I don't get FR_DISK_ERR. But If I remove the card, plug it back, restart the STM32 processor, then I still got the FR_DISK_ERR.

Writing garbage values:

If I write a text string for example this

STM32_PLC_SD_Write_File("Hour,Minute,Second,Millisecond,");
STM32_PLC_SD_Write_File("ADC0,ADC1,ADC2,ADC3,ADC4,ADC5,ADC6,ADC7,ADC8,ADC9,ADC10,ADC11,");
	STM32_PLC_SD_Write_File("DADC0,DADC1,DADC2,DADC3,DADC4,");
	STM32_PLC_SD_Write_File("I0,I1,I2,I3,I4,I5,I6,I7,");
	STM32_PLC_SD_Write_File("E0,E1,");
	STM32_PLC_SD_Write_File("IC0,IC1,IC2,");
	STM32_PLC_SD_Write_File("DAC0,DAC1,DAC2,");
	STM32_PLC_SD_Write_File("PMW0,PWM1,PWM2,PWM3,PWM4,PWM5,PWM6,PWM7\n");
 
/* Return -1 with End of File (EOF) */
static FIL *fil;
int STM32_PLC_SD_Write_File(char text[]) {
	return f_puts(text, fil);
}

Then I got this

$� ADC ��� DADC4 I0 I1 I2 I3 I4 I5 I6 I7 E0 E1 IC0 IC1 IC2 DAC0 DAC1 DAC2 PMW0 PWM1 PWM2 PWM3 PWM4 PWM5 PWM6 PWM7

Hard fault:

Sometimes I just get hard fault when I try to write this. From the beginning, it works OK. Then few seconds later, then I get hard fault. The text array is 200 bytes long.

This code loops every millisecond.

sprintf(text, "%i,%i,%i,%i,",
					hours,
					minutes,
					seconds,
					milliseconds);
			STM32_PLC_SD_Write_File(text);
 
			sprintf(text, "%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,",
					STM32_PLC_Analog_Input_ADC_Get(0),
					STM32_PLC_Analog_Input_ADC_Get(1),
					STM32_PLC_Analog_Input_ADC_Get(2),
					STM32_PLC_Analog_Input_ADC_Get(3),
					STM32_PLC_Analog_Input_ADC_Get(4),
					STM32_PLC_Analog_Input_ADC_Get(5),
					STM32_PLC_Analog_Input_ADC_Get(6),
					STM32_PLC_Analog_Input_ADC_Get(7),
					STM32_PLC_Analog_Input_ADC_Get(8),
					STM32_PLC_Analog_Input_ADC_Get(9),
					STM32_PLC_Analog_Input_ADC_Get(10),
					STM32_PLC_Analog_Input_ADC_Get(11));
			STM32_PLC_SD_Write_File(text);
 
			sprintf(text, "%0.2f,%0.2f,%0.2f,%0.2f,%0.2f,",
					STM32_PLC_Analog_Input_DADC_Get(0),
					STM32_PLC_Analog_Input_DADC_Get(1),
					STM32_PLC_Analog_Input_DADC_Get(2),
					STM32_PLC_Analog_Input_DADC_Get(3),
					STM32_PLC_Analog_Input_DADC_Get(4));
			STM32_PLC_SD_Write_File(text);
 
			sprintf(text, "%i,%i,%i,%i,%i,%i,%i,%i,",
					STM32_PLC_Digital_Input_Get(0),
					STM32_PLC_Digital_Input_Get(1),
					STM32_PLC_Digital_Input_Get(2),
					STM32_PLC_Digital_Input_Get(3),
					STM32_PLC_Digital_Input_Get(4),
					STM32_PLC_Digital_Input_Get(5),
					STM32_PLC_Digital_Input_Get(6),
					STM32_PLC_Digital_Input_Get(7));
			STM32_PLC_SD_Write_File(text);
 
			sprintf(text, "%i,%i",
					STM32_PLC_Encoder_Get(0),
					STM32_PLC_Encoder_Get(1));
			STM32_PLC_SD_Write_File(text);
 
 
			sprintf(text, "%0.2f,%0.2f,%0.2f,",
					STM32_PLC_Input_Capture_Get(0),
					STM32_PLC_Input_Capture_Get(1),
					STM32_PLC_Input_Capture_Get(2));
			STM32_PLC_SD_Write_File(text);
 
 
			sprintf(text, "%i,%i,%i,",
					STM32_PLC_Analog_Output_Get(0),
					STM32_PLC_Analog_Output_Get(1),
					STM32_PLC_Analog_Output_Get(2));
			STM32_PLC_SD_Write_File(text);
 
			sprintf(text, "%i,%i,%i,%i,%i,%i,%i,%i\n",
					STM32_PLC_PWM_Get(0),
					STM32_PLC_PWM_Get(1),
					STM32_PLC_PWM_Get(2),
					STM32_PLC_PWM_Get(3),
					STM32_PLC_PWM_Get(4),
					STM32_PLC_PWM_Get(5),
					STM32_PLC_PWM_Get(6),
					STM32_PLC_PWM_Get(7));
			STM32_PLC_SD_Write_File(text);

This is a result when I do a "successful" logging process.

0693W00000D0tRxQAJ.png 

My SPI settings:

I'm using SPI for writing and reading to the SD card.

0693W00000D0tFIQAZ.pngThis is my FATFS configuration

/* USER CODE BEGIN Header *//** ******************************************* - Pastebin.com

Edit:

After using this library

kiwih/cubeide-sd-card: CubeIDE/CubeMX compatible MMC/SD memory card FatFs driver (github.com)

Things starting to get better now.

I don't get hard fault when I write. So that's good news.

But I get two error codes now. These two.

FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */

FR_NOT_READY, /* (3) The physical drive cannot work */

FR_DISK_ERR will I get when I unplug the SD card and plug it back again for mount.

FR_NOT_READY will I get if I turn of the power for my STM32 processor and then turn back the power again.

To "solve" FR_NOT_READY, i need to reflash the STM32 processor again. But the problems appear directly after I have replug the power (USB voltage) for my STM32 processor.

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

STM32MP257FAK3 custom board with STM64-OS as operating system: https://github.com/DanielMartensson/STM64-Computer
This discussion is locked. Please start a new topic to ask your question.
1 ACCEPTED SOLUTION

Accepted Solutions
DMÃ¥rt
Lead

I solved it now.

Step 1: Use EXACTLY the same code as the GitHub link provides.

Step 2: Use my code.

/*
 * SD_Card.c
 *
 *  Created on: Jun 15, 2021
 *      Author: Daniel MÃ¥rtensson
 */
#include "Functions.h"
#include "user_diskio_spi.h"
#include "fatfs.h"
 
/* These are extern inside fatfs.h */
FATFS USERFatFS;
FIL USERFile;
 
void STM32_PLC_Start_SD(SPI_HandleTypeDef *hspi, GPIO_TypeDef *SD_CS_PORT, uint16_t SD_CS_PIN) {
	SD_init(hspi, SD_CS_PORT, SD_CS_PIN);
}
 
FRESULT STM32_PLC_SD_Mont_Card() {
	FRESULT status;
	uint8_t attempt = 0;
	while(attempt < 255) {
		MX_FATFS_Init();
		status = f_mount(&USERFatFS, "", 1);
		if(status == FR_OK){
			break;
		} else {
			STM32_PLC_SD_Unmount_Card();
			attempt++;
		}
	}
	return status;
}
 
FRESULT STM32_PLC_SD_Unmount_Card() {
	FRESULT status = f_mount(NULL, "", 0);
	MX_FATFS_DeInit();
	return status;
}
 
FRESULT STM32_PLC_SD_Open_Existing_File_With_Read_Write(char filename[]) {
	return f_open(&USERFile, filename, FA_READ | FA_WRITE); /* Posix "r+" */
}
 
FRESULT STM32_PLC_SD_Create_New_File_With_Read_Write(char filename[], char initial_string[], bool overwrite) {
	FRESULT status;
	if(overwrite){
		/* Will always create a new file, so status will always be FR_OK */
		status = f_open(&USERFile, filename, FA_CREATE_ALWAYS | FA_READ | FA_WRITE); /* Posix "w+" */
	}else {
		/* If filename exist, then status will be FR_EXIST, else FR_OK if not exist */
		status = f_open(&USERFile, filename, FA_CREATE_NEW | FA_READ | FA_WRITE); /* Posix "w+x" */
	}
	/* If status is FR_OK, then write the initial string */
	if(status == FR_OK) {
		STM32_PLC_SD_Write_File(initial_string);
		STM32_PLC_SD_Close_File();
	}
	return status;
}
 
FRESULT STM32_PLC_SD_Close_File() {
	return f_close(&USERFile);
}
 
FRESULT STM32_PLC_SD_Check_Space(uint32_t *total_space, uint32_t *free_space) {
	FATFS *pfs;
	DWORD fre_clust;
	FRESULT status = f_getfree("", &fre_clust, &pfs);
	*total_space = (uint32_t) ((pfs->n_fatent - 2) * pfs->csize * 0.5);
	*free_space = (uint32_t) (fre_clust * pfs->csize * 0.5);
	return status;
}
 
/* Return text "error" or "eof" if it's end of file (eof) */
char* STM32_PLC_SD_Read_File(char text[], int len) {
	return f_gets(text, len, &USERFile);
}
 
/* Return -1 with End of File (EOF) */
int STM32_PLC_SD_Write_File(char text[]) {
	return f_puts(text, &USERFile);
}

Add this to user_diskio_spi.c file as well

static SPI_HandleTypeDef*   SD_SPI_HANDLE;
static GPIO_TypeDef*		SD_SPI_CS_Port;
static uint16_t 			SD_SPI_CS_Pin;
 
void SD_init(SPI_HandleTypeDef *hspi, GPIO_TypeDef *SD_CS_PORT, uint16_t SD_CS_PIN) {
	SD_SPI_HANDLE = hspi;
	SD_SPI_CS_Port = SD_CS_PORT;
	SD_SPI_CS_Pin = SD_CS_PIN;
}

Done!

Very robust. The key idea is to mount the SD card until its mounted.

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

STM32MP257FAK3 custom board with STM64-OS as operating system: https://github.com/DanielMartensson/STM64-Computer

View solution in original post

2 REPLIES 2
DMÃ¥rt
Lead

I solved it now.

Step 1: Use EXACTLY the same code as the GitHub link provides.

Step 2: Use my code.

/*
 * SD_Card.c
 *
 *  Created on: Jun 15, 2021
 *      Author: Daniel MÃ¥rtensson
 */
#include "Functions.h"
#include "user_diskio_spi.h"
#include "fatfs.h"
 
/* These are extern inside fatfs.h */
FATFS USERFatFS;
FIL USERFile;
 
void STM32_PLC_Start_SD(SPI_HandleTypeDef *hspi, GPIO_TypeDef *SD_CS_PORT, uint16_t SD_CS_PIN) {
	SD_init(hspi, SD_CS_PORT, SD_CS_PIN);
}
 
FRESULT STM32_PLC_SD_Mont_Card() {
	FRESULT status;
	uint8_t attempt = 0;
	while(attempt < 255) {
		MX_FATFS_Init();
		status = f_mount(&USERFatFS, "", 1);
		if(status == FR_OK){
			break;
		} else {
			STM32_PLC_SD_Unmount_Card();
			attempt++;
		}
	}
	return status;
}
 
FRESULT STM32_PLC_SD_Unmount_Card() {
	FRESULT status = f_mount(NULL, "", 0);
	MX_FATFS_DeInit();
	return status;
}
 
FRESULT STM32_PLC_SD_Open_Existing_File_With_Read_Write(char filename[]) {
	return f_open(&USERFile, filename, FA_READ | FA_WRITE); /* Posix "r+" */
}
 
FRESULT STM32_PLC_SD_Create_New_File_With_Read_Write(char filename[], char initial_string[], bool overwrite) {
	FRESULT status;
	if(overwrite){
		/* Will always create a new file, so status will always be FR_OK */
		status = f_open(&USERFile, filename, FA_CREATE_ALWAYS | FA_READ | FA_WRITE); /* Posix "w+" */
	}else {
		/* If filename exist, then status will be FR_EXIST, else FR_OK if not exist */
		status = f_open(&USERFile, filename, FA_CREATE_NEW | FA_READ | FA_WRITE); /* Posix "w+x" */
	}
	/* If status is FR_OK, then write the initial string */
	if(status == FR_OK) {
		STM32_PLC_SD_Write_File(initial_string);
		STM32_PLC_SD_Close_File();
	}
	return status;
}
 
FRESULT STM32_PLC_SD_Close_File() {
	return f_close(&USERFile);
}
 
FRESULT STM32_PLC_SD_Check_Space(uint32_t *total_space, uint32_t *free_space) {
	FATFS *pfs;
	DWORD fre_clust;
	FRESULT status = f_getfree("", &fre_clust, &pfs);
	*total_space = (uint32_t) ((pfs->n_fatent - 2) * pfs->csize * 0.5);
	*free_space = (uint32_t) (fre_clust * pfs->csize * 0.5);
	return status;
}
 
/* Return text "error" or "eof" if it's end of file (eof) */
char* STM32_PLC_SD_Read_File(char text[], int len) {
	return f_gets(text, len, &USERFile);
}
 
/* Return -1 with End of File (EOF) */
int STM32_PLC_SD_Write_File(char text[]) {
	return f_puts(text, &USERFile);
}

Add this to user_diskio_spi.c file as well

static SPI_HandleTypeDef*   SD_SPI_HANDLE;
static GPIO_TypeDef*		SD_SPI_CS_Port;
static uint16_t 			SD_SPI_CS_Pin;
 
void SD_init(SPI_HandleTypeDef *hspi, GPIO_TypeDef *SD_CS_PORT, uint16_t SD_CS_PIN) {
	SD_SPI_HANDLE = hspi;
	SD_SPI_CS_Port = SD_CS_PORT;
	SD_SPI_CS_Pin = SD_CS_PIN;
}

Done!

Very robust. The key idea is to mount the SD card until its mounted.

STM32MP151AAC3 custom board with STM32-OS as operating system: https://github.com/DanielMartensson/STM32-Computer

STM32MP257FAK3 custom board with STM64-OS as operating system: https://github.com/DanielMartensson/STM64-Computer

Thank you for sharing the solution