2025-02-09 05:20 PM - edited 2025-02-09 05:26 PM
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);
}
2025-02-11 03:15 AM - edited 2025-02-11 03:17 AM
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.
2025-02-11 04:05 AM
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.
2025-02-11 05:42 AM
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.
2025-02-11 08:11 AM
Ozone,
I've worked with a Raspberry Pi, more precisely the Zero, and I really liked it, but unfortunately it burned out and I couldn't use another one.
In my country, unfortunately, things like this are all imported, there are high taxes, and the Dollar/Euro/Pound are not cheap here (like 1 Dollar is 5.79 in my currency), so replacing it is not easy. So I paid attention to this board that I already had with me, using it in a college project, and I really enjoyed working with it.
But yes, I agree with you, that what I want to develop would be easier on a Raspberry with Linux and specialized software, but I like challenges, and I'm enjoying this one. The only part about writing to the SD card that I didn't expect, I managed to solve all the other problems, but this one is complicated, and you're helping me with ideas of what it could be and how to figure it out.
2025-02-12 01:35 AM
> In my country, unfortunately, things like this are all imported, there are high taxes, ...
Yes, surely correct. Not to mention, power requirements, startup times and realtime capabilities might make commercial applications in certain areas challenging.
But back to the topic ...
As said, you can try different cards, and FAT16 formatting.
As a side note, Fatfs is relatively generic, i.e. not written for a specific platform. The mid- and high-level FS code is from the original package, and underlying HAL code (read/write primitives) supplied by the vendor - ST in this case.
Years ago I had to rewrite this HAL layer for a F303 discovery project, to support an external SD card module (driven via SPI, not SDIO).
You might need to debug down into this HAL level to find the reason for your issue.
I never touched a Fatfs implementation based upon ST's Cube/HAL, to be honest.
2025-02-12 02:54 AM
I really appreciate your help. Yesterday I managed to find the problem. Actually, I don't know if there were 2. I first enabled flow control, it didn't work, then I enabled the SDO interrupt, and it worked like a charm.
Ozone, as for fat16, I'll save that tip for another problem, or maybe even a smaller card (I've already made an SD work with an MC68000 CPU using fat16).
2025-02-12 03:08 AM
> Yesterday I managed to find the problem. Actually, I don't know if there were 2. I first enabled flow control, it didn't work, then I enabled the SDO interrupt, and it worked like a charm.
This is the vendor-specific HAL layer. Just saying ...