...Ex() functions and FreeRTOS on STM32

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • ...Ex() functions and FreeRTOS on STM32

    Hello, gentlemen.
    I using function 'IMAGE_SetBMPEx' to show image from SD card.
    My '_GetData' function looks like:

    static char _acBuffer[BYTES_IN_LINE];
    int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Offset){
    unsigned int NumBytesRead;
    if (NumBytesReq > sizeof(_acBuffer)) {// Check buffer size
    NumBytesReq = sizeof(_acBuffer);
    }
    f_lseek((FIL *) p, Offset); //Set file pointer to the required position
    f_read((FIL *) p, (void *) _acBuffer, NumBytesReq, &NumBytesRead); //Read data into buffer
    *ppData = (const U8*) _acBuffer; //set pointer to the buffer
    return NumBytesRead;
    }

    I successfully loaded images from SD card whith and without window manager:

    FATFS fileSystem;
    FIL ImgFile;
    FRESULT res;

    /*Register the file system object to the FatFs module*/
    /*
    * param 1 Pointer to the file system object (NULL:unmount)
    * param 2 Logical drive number to be mounted/unmounted
    * param 3 0:Do not mount (delayed mount), 1:Mount immediately
    */

    if (f_mount(&fileSystem, (TCHAR const*) SD_Path, 0) == FR_OK) {


    /*Open file image with read access*/
    /*
    * param 1 Pointer to the blank file object
    * param 2 Pointer to the file name
    * param 3 Access mode and file open mode flags
    */
    res = f_open(&ImgFile, "IMG1.bmp", FA_OPEN_EXISTING | FA_READ);
    if (res == FR_OK) {
    GUI_BMP_DrawEx(_GetData, &ImgFile, 0, 0);
    }
    }


    and in dialog with windows manager:


    #define ID_IMAGE (GUI_ID_USER + 0x70)


    static const GUI_WIDGET_CREATE_INFO Main_Window_DialogCreate[] =
    {
    ...

    { IMAGE_CreateIndirect, "Image", ID_IMAGE,
    0, 0,
    IMAGE_WIDTH, IMAGE_HEIGHT, 0, 0, 0 }
    ...
    };


    IMAGE_Handle image;


    void WIDGETS_Callback(WM_MESSAGE * pMsg){ //Custom callback function

    switch (pMsg->MsgId) {
    case WM_INIT_DIALOG:
    ....
    image = WM_GetDialogItem(pMsg->hWin, ID_IMAGE);
    if (f_mount(&fileSystem, (TCHAR const*) SD_Path, 0) == FR_OK) {
    /*Open file image with read access*/
    /*
    * param 1 Pointer to the blank file object
    * param 2 Pointer to the file name
    * param 3 Access mode and file open mode flags
    */
    res = f_open(&ImgFile, "IMG1.bmp", FA_OPEN_EXISTING | FA_READ);
    if (res == FR_OK) {
    IMAGE_SetBMPEx(image, _GetData, &ImgFile);
    }
    }


    break;
    ...

    default:
    WM_DefaultProc(pMsg); //Default message handler. p.407
    }

    }


    WM_HWIN Create_GUI(void){

    ...
    WM_HWIN EM_dialog;
    EM_dialog = GUI_CreateDialogBox(Main_Window_DialogCreate, GUI_COUNTOF(Main_Window_DialogCreate), WIDGETS_Callback, WM_HBKWIN, 0, 0);return EM_dialog;}


    And everything works fine - pictures in attachments.
    BUT!
    When I use FreeRTOS, function 'IMAGE_SetBMPEx' doesn't work properly.
    It takes 9 or 10 lines from file and then stops. But GUI works fine, touch data updates without any problem, all button callbacks responses at touches, cursor displays properly, everything fine except BMP image.
    In my example I use BMP 16 bit per pixel image that has size 560x320. In one loop through function '_GetData', it takes 1124 bytes.
    On 9 or 10 (every time it different) loop cycle, it takes less than 1124 and after that goes to GUI thread and execute 'GUI_Exec();'
    I tried different approaches, I used semaphores, play with preemption and Suspend-Resume functions, but all the same.
    Cause library is completely closed I can't see in debug mode the cause of the problem.


    My platform:
    MCU: STM32F103ZET6 (without any external SRAM or SDRAM)
    LCD: 7" 800 x 480 with Solomon's SSD1963 controller (1215kB VRAM).
    SD connected through SDIO SD 1 bit protocol. (yes, it loads pretty slowly - nearly 1 second)


    System configuration:
    for emWin:
    #define GUI_NUMBYTES (20*1024)

    for RTOS:
    #define configTOTAL_HEAP_SIZE ((size_t)30 * 1024)



    F103ZET6 has 64kB of RAM and 512kB of ROM.

    Whole project you can take from my yandex disk:
    https://yadi.sk/d/sNU3ivowug4j9


    B.R. Constantine Laskov.


    Some details about this project you can also find at my site:
    http://microelk.azurewebsites.net/


  • I found the cause of trouble.
    When functions IMAGE_SetBMPEx calls function _GetData it doesn't block it. So in the middle of read cycle it breaks by any other thread even with less priority.
    So there is no solution, there is just some workaround - to suspend all threads in your system before reading cycle from FAT FS device, and resume it after.
    This definetly BUG in function. Cause blocking should be done inside it (or some parameter should be added) and not implemented by user's code.
    No semaphores or mutexes applied to thread that contains function IMAGE_SetBMPEx changes this situation, just straight and stupid blocking all threads inside _GetData function. In my case threads that breaks loading is a technology thread (I'm doing PLC) and touch thread.


    I spend two days to find this bug (RAD and emWin? Is it possible?). I implemented stack overflow control, heap allocation control and nothing gives any clue to solution.
    Description of function IMAGE_SetBMPEx in manual is poor. No any examples can be found. No any description how it works either.
    Pretty bad support for pretty expensive library.


    B.R. Constantine.
    :cursing:

    The post was edited 1 time, last by Constantine ().

  • Hi Constantine,

    This definetly BUG in function.

    Nope. There is no bug in that function.
    Did you had a look in the chapter "Execution Model: Single Task / Multitask" in the emWin manual?
    Did you add the according FreeRTOS functions?

    Description of function IMAGE_SetBMPEx in manual is poor. No any examples can be found.

    The IMAGE_SetBMPEx() description refers to the GetData description and there are several examples:
    Pointer to the GetData()-function. Details on how to implement a GetData()-function
    can be found under “Getting data with the ...Ex() functions” on page 187.



    Pretty bad support for pretty expensive library.

    Please be aware you are using STemwin and not Segger emWin.
    STemWin support is only done by ST.
    Did you contact the ST suport?
    If you are not happy with the ST suport you can get an emWin license and the support directly from Segger.

    Best regards,
    Til
  • Hi, Til.
    Thanks for reply.
    1. Yes I read emWin manual from the beginning to the end and not even once. (I look it regular in metro at morning, without joking)
    Yes I checked for these functions. STM's engineers have already added it in file GUI_X_OS.c:

    /* Get Task handle */
    U32 GUI_X_GetTaskId(void)
    {
    return ((U32) osThreadGetId());
    }




    void GUI_X_WaitEvent (void)
    {
    osSemaphoreWait(osSemaphore , osWaitForever) ;
    }




    void GUI_X_SignalEvent (void)
    {
    osMutexRelease(osSemaphore);
    }
    As you can see they use CMSIS RTOS API.

    1.1. All necessary definitions for multitasking are also made. (It is provided in STemWin library). If there were some errors, all widgets wouldn't work.

    2. I looked for example of _GetData function provided in emWin manual. Even if it is abstract, I built similar function based on STM's examples.
    Main problem is that it isn't working proper with RTOS and I can't debug it cause its execution ceases by ...Ex function, that is completely undebugable. No errors, no other respond.

    3. I agree, the main problem that there are no examples provided by STM for ...Ex function implementation. (Just VideoPlayer for M7 platform that is in my case useless - another driver, another _GetData function). But SEGGER also usually provides examples for emWin's functions that I can't find for ...Ex functions. Just brief description in emWin.
    Behavior of these functions is pretty peculiar in multitasking environment. I still can't apprehend it completely. Main difficulty is that it is the slowest process in system. And it is pretty difficult to understand why it is impossible to block RTOS on this function for its successful completion.

    So, I agree that this is not a bug. Maybe here it is better to say that it is undocumented specific behavior of this function in multitasking environment.
    But for me, like for the end user it has absolutely equal result.

    And finally, company Segger provides RTOS, File System and GUI solution. Is it so difficult to provide more detailed example of ...Ex() functions implementation even based on this libraries?


    B.R. Constantine.
  • Good day dear Segger.
    Is it possible to make your utilities useful?
    I use Microsoft Visual Studio Community for my little utilities.
    It is absolutely free and produces good-looking GUI.
    I'm recommending it to your company.

    B.R. Constantine.
    P.S. I buy your product for 500$:
    chipdip.ru/product/j-link-usb-jtag-adapter/
    And again I have bad support for pretty expensive tool.
    Images
    • 2016-09-03_19-38-48.png

      47.26 kB, 1,354×520, viewed 571 times
  • I found solution:
    In case of RTOS you should prevent interrupting of SD reading process. My functions looks like this:


    U8* _acBuffer;

    static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Offset) {
    unsigned int NumBytesRead;
    // if (NumBytesReq > sizeof(_acBuffer)) //Check buffer size
    // NumBytesReq = sizeof(_acBuffer);
    taskENTER_CRITICAL(); //Prevent the possibility to break SD read process
    // osThreadSetPriority(ImgCyclerHandle, osPriorityRealtime); //Prevent the possibility to break SD read process
    f_lseek((FIL *) p, Offset); //Set file pointer to the required position
    f_read((FIL *) p, (void *) _acBuffer, NumBytesReq, &NumBytesRead); //Read data into buffer
    // osThreadSetPriority(ImgCyclerHandle, osPriorityNormal); //Restore GUI thread priority
    taskEXIT_CRITICAL();
    *ppData = (const U8 *) _acBuffer; //Set pointer to the buffer
    return NumBytesRead;
    }

    /*
    * This function loads image from SD in emWin widget 'GUI_BMP_DrawEx'
    * from SD through FAT FS
    */
    void Show_img_from_SD(TCHAR const* img_name) {
    _acBuffer = (U8*) calloc(BYTES_IN_LINE, sizeof(U8));
    /*Register the file system object to the FatFs module*/
    /*
    * param 1 Pointer to the file system object (NULL:unmount)
    * param 2 Logical drive number to be mounted/unmounted
    * param 3 0:Do not mount (delayed mount), 1:Mount immediately
    */
    if (f_mount(&fileSystem, (TCHAR const*) SD_Path, 0) == FR_OK) {

    /*Open file image with read access*/
    /*
    * param 1 Pointer to the blank file object
    * param 2 Pointer to the file name
    * param 3 Access mode and file open mode flags
    */
    res = f_open(&ImgFile, img_name, FA_OPEN_EXISTING | FA_READ);
    if (res == FR_OK)
    GUI_BMP_DrawEx(_GetData, &ImgFile, 0, 0);
    f_close(&ImgFile);
    }
    f_mount(NULL, (TCHAR const*) SD_Path, 0);
    free(_acBuffer);
    }

    That's all for this thread.
    P.S.:
    Jlink interface still bad.
    Thanks to Til, his comments were completely useless.

    The post was edited 1 time, last by Constantine ().

  • So, finally I've found what the problem in current situation.
    emWin block resourses by using mutexes.
    Look for description of functions: GUI_X_Lock() and GUI_X_Unlock()
    It prevents LCD from double access - some kind of gatekeeping. That is fine.
    But it doesn't block processes from interrupting by other threads. In case of using LCDs with parallel interface it is not a problem - interface takes data per one tick on 'E' pin and can wait until other process, that interrupt current GUI to LCD transaction will finish its job.

    But in case emWin library utilizes some serial interface - SDIO (in my case), I2C or SPI, it can become the cause of similar like described above issue (except I2C - it can wait). If you suspend SPI of SDIO in the middle of transaction, you definetelly will receive hardfault or some other kind of error.
    So I think everyone who uses SPI displays with RTOS can have similar issues.
    In this case, I think emWin engineers should include some kind of description in manual, or mabe even create some special API for this function.
    In case of FreeRTOS I guarded SDIO process by freezing scheduler - look code above.

    B.R. Constantine.
  • No, Sven. It is not.
    Yes function is working, but it still consumes memory until whole GUI runs out of it. This is another thread, I have some trouble with ...Ex() functions at the beginning - it breaks at half of picture. I found solution for this trouble. But I can't resolve issue with memory management.
    And I still can't found workaround, cause couple GUI_Exit -> GUI_Init not working proper under RTOS.


    B.R. Constantine.

    The post was edited 1 time, last by Constantine ().

  • Sven, I think I found workaround. But solution is pretty weak and unstable.
    Call me, I think we should discuss it before I issue some code. Maybe you can explain some details about emWin RTOS implementation.
    mob.: 8 965 318 22 82

    P.S. Yes I read chapter 17, I think that on present moment I know your manual nearly by heart.
    Yes I checked GUI_X_OS and GUIConf files. For me it looks normal.