Skip to main content
Mario Gkiolena
Associate
February 11, 2018
Question

STM32Cube_FW_F4_V1.19.0 + FREERTOS + FATFS + SDIO + DMA

  • February 11, 2018
  • 9 replies
  • 2800 views

Posted on February 11, 2018 at 17:59

Hello,

I am using a custom board with an STM32F401RB microcontroller that I want to be able to save data to SD Card. At first I tried without using FreeRTOS and I found that writing data every 20ms is not applicable because every writing cycle sometimes took about 150ms and from specifications can take up to 250ms. So I thought to give a try on FreeRTOS (it is my first time with FreeRTOS and I am currently reading the documentations). I made a basic cube project just for the SD Card with slow SDIO speed (1MHz) that I have posted here. I run the code above to test if the SDIO and FatFS driver works but keeps failing. Am I missing something?

/* StartDefaultTask function */

void StartDefaultTask(void const * argument)

{

/* init code for FATFS */

MX_FATFS_Init();

/* USER CODE BEGIN 5 */

FATFS fs;

FIL fil;

FRESULT res;

char mybuff[64];

/* Infinite loop */

for(;;)

{

res = f_mount(&fs, '', 1);

if (res){

sprintf(mybuff, 'failed, %u', res);

}

/* Create a file as new */

res = f_open(&fil, 'speed.txt', FA_OPEN_ALWAYS | FA_WRITE);

if (res){

sprintf(mybuff, 'failed, %u', res);

}

/* Close the file */

res = f_close(&fil);

if (res){

sprintf(mybuff, 'failed, %u', res);

}

osDelay(1000);

}

/* USER CODE END 5 */

}

This topic has been closed for replies.

9 replies

Tesla DeLorean
Guru
February 13, 2018
Posted on February 13, 2018 at 18:55

Mounting, opening, closing files is going to be slow.

You're goal for any speed is to write multiples of 512 bytes, ideally a buffer of 32KB in an aligned fashion.

I would recommend using the HAL examples, number of complaints with CubeMX, and not something I'm going to wade into.

When debugging you're going to need to inspect the DISKIO layer as errors in the SDIO access will simply propagate up to the FatFS level. There are many things that can induce failure.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Mario Gkiolena
Associate
February 14, 2018
Posted on February 14, 2018 at 01:10

So are you suggesting to use the example that is located in 

\STM32Cube\Repository\STM32Cube_FW_F4_V1.19.0\Projects\STM32F412G-Discovery\Applications\FatFs\FatFs_uSD_RTOS

as a base instead of cube's code?

On the cube's code I realized that the SD card operations were in blocking mode and in order to not loose my sampling data that I manually need to take every 20 ms or it gets lost (no interrupt), I need to use FreeRTOS. I do not mind to save the data every 0.5 seconds in 512 blocks which means that if I use a double buffer I just need 3.2k of RAM that isn't a problem. You said that the data should be

 aligned, is't that take care of FATFS? If not how can I

aligned it with FATFS functions?

Tesla DeLorean
Guru
February 14, 2018
Posted on February 14, 2018 at 06:36

I'm suggesting I'm not going to fire fight issues with CubeMX generated code, the straight HAL examples in my experience are more robust, I wouldn't go as far as saying they have been rigorously tested.

Yes, FatFs will manage the sectors and blocking for you, but it also exposes the worst case characteristics of the underlying medium, ie MicroSD with large erase blocks. For efficiency sake don't call f_read/f_write a million times dealing with a dozen bytes at a time, access large blocks, say 32KB, on 32KB boundaries within the file. ie things which are aligned and coherent with the blocking within the device. Things that don't need managing are pass down to the DISKIO layer unmolested, ie f_write() a 32KB block, and DISKIO can do a multi-sector write with minimal command/response overhead.

You don't need an RTOS, collect/accumulate data in an interrupt context, and periodically flush to a file in the foreground. I can write several MB per second on an F412-DISCO (32KB at a time), and 1.6 MBps would equate to 32KB at 50Hz. I have real-time data loggers that can run for months without losing data or interrupts.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Willem La Grange
Associate
February 15, 2018
Posted on February 15, 2018 at 17:11

Firstly you do not mention if you are using SDIO or SPI. The second think that I notice is that you are not looking at the result codes from all the opperations. The result codes will tell you a lot why your program is failing. From What I see, I think that you are probably running out of memory. Depending on you settings you must either increase the heap or the cstack on the linker.

Here is some code I used to send the error codes via USB

int main()

{

   FATFS *mFatFs = &FatFs;

    FRESULT Fresult;

    char mPath[4]; /* User logical drive path */

    memset(&mPath, 0, sizeof(mPath));

    Fresult = f_mount(mFatFs, (TCHAR const*)&mPath, 1);

    SendUSBresult('Mount:', Fresult);

}

void SendUSBresult(char *Mess, FRESULT FResult)

{

    static char myMess[100];

    memset(&myMess,0,sizeof(myMess));

    sprintf(myMess, '%s %s\r\n',Mess,f_put_rc(FResult));

    if(Diagnostic_On)

    {

        CDC_Transmit_FS((unsigned char *) myMess, strlen(myMess));

    }

    HAL_Delay(4);

}

char *f_put_rc(FRESULT rc)

{

   return put_rc(rc);

}

static char *put_rc (FRESULT rc)

{

        static char Retstr[50];

 const char str[][20] = {

  'OK\0' ,'DISK_ERR\0' ,'INT_ERR\0', 'NOT_READY\0', 'NO_FILE\0' ,'NO_PATH\0',

  'INVALID_NAME\0' ,'DENIED\0' ,'EXIST\0' ,'INVALID_OBJECT\0' ,'WRITE_PROTECTED\0' ,

  'INVALID_DRIVE\0' ,'NOT_ENABLED\0', 'NO_FILE_SYSTEM\0', 'MKFS_ABORTED\0' ,'TIMEOUT\0'

                  'LOCKED\0' ,'NOT_ENOUGH_CORE\0' ,'TOO_MANY_OPEN_FILES\0'};

        if(rc > 19) rc = FR_DISK_ERR;

 sprintf((char*)&Retstr[0],'rc=%u FR_%s\n', (UINT)rc, str[(UINT)rc]);

        return (char*)&Retstr;

}
Mario Gkiolena
Associate
February 15, 2018
Posted on February 15, 2018 at 19:15

I have posted the .ioc so you can see from there that I am using SDIO.

I can see the errors that is producing, that's why I am writing the result and print it on a buffer to see it through the debugger. The error that I am getting through FATFS is 1 (

DISK_ERR

). I have also stepped through the code and got a timeout from the card. I will debug again the code and post exactly where I am getting the error.

I have also tried to increase the heap and stack size without any success, so if I not missing something it isn't an memory issue. I think on the .ioc that I have posted the stack and heap is about 0x800 and 0x1000.

Willem La Grange
Associate
February 15, 2018
Posted on February 15, 2018 at 20:18

Hi Mario,

Depending on the requirements of you other code that is not an awfull lot.

This is what I used on my project:

define symbol __ICFEDIT_size_cstack__ = 0x1500;

define symbol __ICFEDIT_size_heap__   = 0x2000;

Remember the RAM size depends on the SD card that you insert. It needs to be able to load the complete FAT table (depending on your settings)

If the problem is not memory, then you have one of two possible errors (or both)

1. Your SD card does not initialize. That means that you have not editing your low level drivers. Go to

http://elm-chan.org/fsw/ff/00index_e.html

 and scroll down to 'Resources'. Read the module application note and download the FATFS sample projects. Choose your hardware platform and only use their diskio.h and diskio.c files.

2. Your SD hardware resets prematurely. Check your hardware. Make sure that you have at least a 2.2uF capacitor directly across the power pins of the SD card socket.

I hope it helps.

 You can mail me at willem(at)stima.co.za