cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Cube_FW_F4_V1.19.0 + FREERTOS + FATFS + SDIO + DMA

Mario Gkiolena
Associate II

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 */

}

9 REPLIES 9
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
Up vote any posts that you find helpful, it shows what's working..
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?

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
Up vote any posts that you find helpful, it shows what's working..
Posted on February 14, 2018 at 10:06

If I was able to use interrupts I wouldn't have any problem but unfortunately I can't. I am bound to use a proprietary driver that I don't really know that is really doing (close sourced) and in the application recommendation they didn't use it inside the interrupts so that tells me that I shouldn't ether. My problem is that even with a

cluster write

I can't accept a latency for more that 18ms or with a bit of modification maybe about 38ms because I will lose data. I really hate propriety code!

Thank you very much for your help because I didn't know that those examples existed for HAL and they really look better they remind me the examples of the STD. I will try them as soon as possible and post back!

If happened that you tried a lot of SD cards do you have any recommendation for speed and power consumption?

Posted on February 15, 2018 at 15:52

Hi,

If you cannot change the card driver, you might be able to change how you acquire the data. You might need to implement some circular buffering scheme, where the data is buffered while the long write happens to the card.

Alex R.

Willem La Grange
Associate II
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;

}
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.

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

Posted on February 18, 2018 at 08:22

So I tries the example I made all the changes that needed for the project that is located to 

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

to work with the stm32f401rb but unfortunately it didn't. I steped throuth the code and I got CRC_FAIL errors every time! I read the errata

http://www.st.com/content/ccc/resource/technical/document/errata_sheet/df/f5/fd/26/37/db/42/2b/DM00095523.pdf/files/DM00095523.pdf/jcr:content/translations/en.DM00095523.pdf

of the stm32f401rb and found that for the SDIO and found that on page 25 and paragraph 2.9.2 this is stated 

Wrong CCRCFAIL status after a response without CRC is received

Description

The CRC is calculated even if the response to a command does not contain any CRC field. As a consequence, after the SDIO command IO_SEND_OP_COND (CMD5) is sent, the CCRCFAIL bit of the SDIO_STA register is set.

Workaround

The CCRCFAIL bit in the SDIO_STA register shall be ignored by the software. CCRCFAIL must be cleared by setting CCRCFAILC bit of the SDIO_ICR register after reception of the response to the CMD5 command.

So my question is if those problems are taken into consideration when ST makes their examples and software or those are my problems that makes their code unable to run on my core (the stm32f412zg the core that the example was build has the same problem on the SDIO).