Skip to main content
Explorer II
February 10, 2025
Solved

stm32cubeide fatfs f_close FS_DISK_ERR

  • February 10, 2025
  • 3 replies
  • 2671 views

I have a board with stm32f407zgt6. I'm using freertos and fatfs. The board has a connection for an SDCARD, I'm using a 4GB SDCARD with fat32.

For reading, F_open, f_read, f_close, everything works. When I use it to write, f_close takes a long time and returns FS_DISK_ERR.

What do you need, files, the .ioc, the sources, no problem, to help me find the problem? I tried to configure it as correctly as possible, but I think I left something behind.

The write process it's in the file ESP8266_HALL.cpp, this file I put in the body of the post, because the forum did not accept the file for a reason that I did not understand, but I will not fight with the forum, I really want help.

Thank you very much.

PS: f_write return the correct amount of bytes written, with what I ordered to be written. the file, after the f_close error, has 0 bytes on the disk. This happens both for already existing files and for new files

 

 

/*
 * ESP8266_HAL.c
 *
 * Created on: Apr 14, 2020
 * Author: Controllerstech
 */


#include "UartRingbuffer_multi.h"
#include "ESP8266_HAL.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "fatfs.h"
#include "MCUFRIEND_kbv.h"

extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;

extern TIM_HandleTypeDef htim11;
extern TIM_HandleTypeDef htim13;

#define wifi_uart &huart1
#define pc_uart &huart2

#define FORWARD 1
#define BACKWARD 2
#define BRAKE 3
#define RELEASE 4

extern MCUFRIEND_kbv tft;

char buffer[20];

char *Basic_inclusion = (char*)"<!DOCTYPE html> <html>\n<head><meta name=\"viewport\"\
		content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n\
		<title>MMSJ800</title>\n<style>html { font-family: Helvetica; \
		display: inline-block; margin: 0px auto; text-align: center;}\n\
		body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\
		h3 {color: #444444;margin-bottom: 50px;}\n.p {font-size: 14px;color: #888;margin-bottom: 10px;}\n\
		</style>\n</head>\n<body>\n<h1>MMSJ800</h1>\n";

char *Terminate = (char*)"</body></html>";



/*****************************************************************************************************************************************/

//--------------------------------------------------------------------------------
char ESP_Init (char *SSID, char *PASSWD)
{
	char data[80];
	Ringbuf_init();
	char vError = 0;

	Uart_sendstring("\r\n\r\nStarting...\r\n", pc_uart);

	tft.print(".");
	Uart_sendstring("AT+RST\r\n", wifi_uart);
	Uart_sendstring("RESETTING.", pc_uart);
	for (int i=0; i<5; i++)
	{
		HAL_Delay(1000);
	}

	/********* AT **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("AT\r\n", wifi_uart);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
		{
			Uart_sendstring("OK\r\n", pc_uart);
			break;
		}
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			Uart_sendstring("Error\r\n", pc_uart);
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		tft.print("...Error!!!");
		Uart_sendstring("\r\nAT---->ERROR\r\n", pc_uart);
		return -1;
	}

	tft.print(".");
	Uart_sendstring("\r\nAT---->OK\r\n", pc_uart);

//	tft.fillScreen(TFT_BLACK);
//	tft.setCursor(0, 16);

	/********* AT+CWJAP="SSID","PASSWD" **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("connecting... to the provided AP\r\n", pc_uart);
	sprintf (data, "AT+CWJAP=\"%s\",\"%s\"\r\n", SSID, PASSWD);
	Uart_sendstring(data, wifi_uart);
	HAL_Delay(3000);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("Error Connecting\r\n", pc_uart);
		return -1;
	}

	tft.println(".");
	sprintf (data, "Connected to \"%s\"", SSID);
	tft.print(data);
	Uart_sendstring(data,pc_uart);
	Uart_sendstring("\r\n",pc_uart);

	/********* AT+CWMODE=1 **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("AT+CWMODE=1\r\n", wifi_uart);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("CW MODE---->ERROR\r\n", pc_uart);
		return -1;
	}

	tft.print(".");
	Uart_sendstring("CW MODE---->OK\r\n", pc_uart);

	/********* AT+CIFSR **********/
/*	Uart_flush(wifi_uart);
	Uart_sendstring("AT+CIFSR\r\n", wifi_uart);
	HAL_Delay(3000);
	while(1)
	{
		if (Wait_for((char*)"CIFSR:STAIP,\"", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("CIFSR---->ERROR\r\n", pc_uart);
		return -1;
	}
	while (!(Copy_upto((char*)"\"",buffer, wifi_uart)));
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("Error Getting IP\r\n", pc_uart);
		return -1;
	}

	int len = strlen (buffer);
	buffer[len-1] = '\0';
	sprintf (data, "IP ADDR: %s\r\n", buffer);
	Uart_sendstring(data, pc_uart);*/

	/********* AT+CIPSTA **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("Setting Static IP...\r\n", pc_uart);
	sprintf (data, "AT+CIPSTA=\"192.168.0.67\",\"192.168.0.1\",\"255.255.255.0\"\r\n");
	Uart_sendstring(data, wifi_uart);
	HAL_Delay(3000);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("Error Connecting\r\n", pc_uart);
		return -1;
	}

	tft.print(".");
	sprintf (data, "Static IP set to 192.168.0.67\r\n");
	Uart_sendstring(data,pc_uart);

	/********* AT+CIPMUX **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("AT+CIPMUX=1\r\n", wifi_uart);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("CIPMUX---->ERROR\r\n", pc_uart);
		return -1;
	}

	tft.print(".");
	Uart_sendstring("CIPMUX---->OK\r\n", pc_uart);

	/********* AT+CIPSERVER **********/
	Uart_flush(wifi_uart);
	Uart_sendstring("AT+CIPSERVER=1,80\r\n", wifi_uart);
	while(1)
	{
		if (Wait_for((char*)"OK\r\n", wifi_uart))
			break;
		else if (Wait_for((char*)"Error\r\n", wifi_uart))
		{
			vError = 1;
			break;
		}
	}
	if (vError)
	{
		Uart_sendstring("CIPSERVER---->ERROR\r\n", pc_uart);
		return -1;
	}

	tft.println(".");
	tft.print(data);
	Uart_sendstring("CIPSERVER---->OK\r\n", pc_uart);
	Uart_sendstring("Now Connect to the IP ADRESS\r\n", pc_uart);

	return 0;
}

//--------------------------------------------------------------------------------
int Server_Send (char *str, int Link_ID)
{
	int len = strlen (str);
	char data[80];

	sprintf (data, "AT+CIPSEND=%d,%d\r\n", Link_ID, len);
	Uart_sendstring(data, wifi_uart);
	while (!(Wait_for((char*)">", wifi_uart)));
	Uart_sendstring (str, wifi_uart);
	while (!(Wait_for((char*)"SEND OK", wifi_uart)));
	sprintf (data, "AT+CIPCLOSE=5\r\n");
	Uart_sendstring(data, wifi_uart);
	while (!(Wait_for((char*)"OK\r\n", wifi_uart)));
	return 1;
}

//--------------------------------------------------------------------------------
void Server_Handle (char *str, char *resphttpcode, int Link_ID)
{
	int len = strlen (str);
	char response[200];

 sprintf(response,
 "HTTP/1.1 %s\r\n"
 "Content-Type: text/plain\r\n"
 "Content-Length: %d\r\n"
 "Connection: close\r\n"
 "\r\n"
 "%s", resphttpcode, len, str);

	Server_Send(response, Link_ID);
}

//--------------------------------------------------------------------------------
void Server_Start (void)
{
	char buftocopyinto[512] = {0};
	char Link_ID, cRec;
	int ix, indx;
	unsigned int postLen, lenSave, vhead, vtail, timeout;
	char* vPosIni;
	char data[320];
	char slen[10];
	char filename[12];
	FIL basicFile;
	FRESULT res;

	while (!(Get_after((char*)"+IPD,", 1, &Link_ID, wifi_uart)));

	Link_ID -= 48;

	while (!(Copy_upto((char*)"\r\n\r\n", buftocopyinto, wifi_uart)));

//	Uart_sendstring(buftocopyinto, pc_uart);

	if (strstr(buftocopyinto, "/PING")) 
	{
		Server_Handle((char*)"...PONG",(char*)"200 OK",Link_ID);
		Uart_flush(wifi_uart);
	}
	else if (strstr(buftocopyinto, "/SendBasic"))
	{
		// Rotina pra Receber o Arquivo e salvar no SD
		// Somente Arquivos Textos
		// Recebe até, inclusive, o EOF (CHR(26))

		// Pega o nome do arquivo
		memset(filename,0,12);
		GetDataFromBuffer((char*)"filename=", (char*)"&", buftocopyinto, filename);

		// Procura o content-length
		vPosIni = strstr(buftocopyinto,"Content-Length:");
		indx = 0;
		slen[0] = 0;
		if (vPosIni)
		{
			while (1)
			{
				if (*vPosIni >= 0x30 && *vPosIni <= 0x39)
				{
					slen[indx++] = *vPosIni;
					slen[indx] = 0;
				}
				
				if (*vPosIni < 0x20)
					break;
				
				vPosIni++;
			}
		}
		postLen = atoi(slen);

		// Le o corpo
		timeout = 999999;
		memset(buftocopyinto, 0, 512);
		while (!(Get_after((char*)"MMSJ800BEGINOFFILE", (postLen - 18), buftocopyinto, wifi_uart)) && timeout) timeout--;

		if (!timeout)
			strcpy(buftocopyinto, "Incorrect Data Submission Structure\r\n");

		postLen -= 18;

		// Salva Arquivo no Disco
		res = f_open(&basicFile, filename, FA_OPEN_ALWAYS | FA_WRITE);
		if (res == FR_OK)
		{
			res = f_write(&basicFile, buftocopyinto, postLen, &lenSave);
			if (res == FR_OK)
			{
				sprintf(data, "Closing File %s, Size %lu, Written %lu...\r\n", filename, postLen, lenSave);
				Uart_sendstring(data, pc_uart);

				Uart_sendstring((char*)"Returning Response...\r\n", pc_uart);

				res = f_close(&basicFile);
				if (res == FR_OK)
				{
					if (lenSave < postLen)
					{
						sprintf(data, "[301]WARNING! Disk is full, bytesToWrite = %lu, bytesWritten = %lu", postLen, lenSave);
						Server_Handle(data,(char*)"200 OK",Link_ID);
					}
					else
						Server_Handle((char*)"[100]File saved successfully",(char*)"200 OK",Link_ID);
				}
				else
				{
					sprintf(data, "[403][%d]Failed to close file", res);
					Server_Handle(data,(char*)"400 Bad Request",Link_ID);
				}
			}
			else
			{
				sprintf(data, "[401][%d]Failed to save file", res);
				Server_Handle(data,(char*)"400 Bad Request",Link_ID);
			}
		}
		else
		{
			sprintf(data, "[402][%d]Failed to open file to save", res);
			Server_Handle(data,(char*)"400 Bad Request",Link_ID);
		}

		Uart_flush(wifi_uart);
	}
	else if (strstr(buftocopyinto, "/LoadFile"))
	{
		// Rotina pra Enviar Arquivo
		// Somente Arquivos Textos
		// Envia até, inclusive, o EOF (CHR(26))

		// Retorna Resposta
		Server_Handle((char*)"File Sent Successfully",(char*)"200 OK",Link_ID);
	}
	else if (strstr(buftocopyinto, "/Exemplo")) // Apenas Exemplo Rec Parametros
	{
		// Apenas exemplo rec parametro
		/*vPosIni = strstr(buftocopyinto, "/Exemplo");
		if (vPosIni != 0)
		{
			vPosIni += 9;	// Comeca a pegar dados depois da posicao (Len + 1)
			ix = 0;
			sSpeed[ix] = 0;
			while(1)
			{
				if (*vPosIni == ' ')
					break;

				sSpeed[ix++] = *vPosIni++;
				sSpeed[ix] = 0;
			}

			vSpeed = atoi(sSpeed);
		}*/

		// Setar valor PWM
		Server_Handle((char*)"/Exemplo",(char*)"200 OK",Link_ID);
	}
	else
		Server_Handle((char*)"Bad Request",(char*)"400 Bad Request",Link_ID);
}

 

 

 

    This topic has been closed for replies.
    Best answer by Ozone

    As a side note ...

    > I have a board with stm32f407zgt6. I'm using freertos and fatfs. The board has a connection for an SDCARD, I'm using a 4GB SDCARD with fat32.

    > For reading, F_open, f_read, f_close, everything works. When I use it to write, f_close takes a long time and returns FS_DISK_ERR.

    I very well remember that a size if 4GB should be supported, even some while ago.
    However, I found the SD card /fatfs support of many Cortex M boards is generally quite wonky. Some sizes and manufacturers worked, others simply did not. And "across the board", i.e. other vendor's boards have the same problem. I had a similiar issue with a LPC device. Create, open and read seemed to work, but write always failed.

    You could try a FAT16 file system, SDs of other size, or other vendors.

    3 replies

    Super User
    February 10, 2025

    @MSilv.1 wrote:

    f_close takes a long time and returns FS_DISK_ERR.


    So what debugging have you done to find where &  why it does that?

    It's open-source - so you can step into the f_close() function ...

    MSilv.1Author
    Explorer II
    February 10, 2025

    Thanks for the reply. I appreciate it. Yes, only after looking at the code and trying to identify where the problem is, I opened the post here on the forum. I didn't identify a problematic point. It seems that when it writes to the disk, it loses some reference or can't access the SD even.

    The debug you mentioned, this week I upgraded from cubeide 1.13.0 to 1.17.0, and lost the configuration or changed something, and it doesn't work anymore. It doesn't recognize the ST-LINK. I'll see if I can try to configure it again tonight...

    At the same time, I'm doing a hardcode debug, putting messages and showing variables inside the program (sending to usart). I want to see if this way I can at least find the exact location of the delay.

    OzoneAnswer
    Explorer
    February 11, 2025

    As a side note ...

    > I have a board with stm32f407zgt6. I'm using freertos and fatfs. The board has a connection for an SDCARD, I'm using a 4GB SDCARD with fat32.

    > For reading, F_open, f_read, f_close, everything works. When I use it to write, f_close takes a long time and returns FS_DISK_ERR.

    I very well remember that a size if 4GB should be supported, even some while ago.
    However, I found the SD card /fatfs support of many Cortex M boards is generally quite wonky. Some sizes and manufacturers worked, others simply did not. And "across the board", i.e. other vendor's boards have the same problem. I had a similiar issue with a LPC device. Create, open and read seemed to work, but write always failed.

    You could try a FAT16 file system, SDs of other size, or other vendors.

    MSilv.1Author
    Explorer II
    February 11, 2025

    Ozone,

     

    Excellent idea.. In fact, I thought about using FAT16, but I thought it wouldn't be a good idea, but your logic is really correct. It might work better with FAT16. And I don't need a fast or improved FAT, I just need one that allows me to write and read files.

    I'll test it and get back to you.

    Once again, thank you very much for your help.

    Explorer
    February 11, 2025

    I don't know if it solves the issue.
    Fatfs is included in most vendor-specific BSPs and SDKs, but the quality and age/version differs.
    And since SD card access is not a common commercial use case, the respective code often lacks maintainance, to say the least ...

    Since I use this mostly for my private projects, I'm free to choose any hardware platform I'm comfortable with - and for projects with such persistence requirements, I mostly switched to Linux SBCs.

    You get e.g. a Raspberry Pi Zero or Zero 2 for well below 20 bucks ($, €, £), at par with MCU boards.
    But with a much greater choice of development environments, and much higher performance. 

    MSilv.1Author
    Explorer II
    February 11, 2025

    Yesterday I decided to work with the IOC, and I started to change the settings, nothing solved the problem, but I ended up discovering that the problem is not in f_close, but in f_write, more specifically in this function, disk_write. I even tried to see if the SD was not write-protected, I got another 4GB SD, formatted it again with FAT32, this time completely, without being fast, but nothing. I'm thinking that it may not be an error in fatfs, but in the SD controller, it may have broken or caused some problem.

    I'm going to see if there's a way to make fatfs work with an SD external to the board, and test it, if everything works, I'll lose some pins, and isolate the SD from the board.