2021-07-28 07:21 AM
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.
My SPI settings:
I'm using SPI for writing and reading to the SD card.
This 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.
Solved! Go to Solution.
2021-07-28 04:06 PM
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.
2021-07-28 04:06 PM
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.
2021-07-29 02:23 AM
Thank you for sharing the solution