FreeRTOS and emWin on STM32F4

Hi! I’m trying to get Segger emWin working with FreeRTOS. I’m building an user interface using the LCD and Touchscreen from the stm32f4-eval. I would like to know if I’m correctly structuring my project. In my interface there are 2 buttons, the first one creates a graph window in which I show the square wave of a led blinking (the led toggles within a TIM interrupt), the second one creates a graph too, in wich I show data coming from the IMU. I create into the main function the first backgrund task, which creates the interface and, in turn, creates also other two tasks, adding values to the graphs. My code works quite well, but 9 times out of 10 I can’t get the two graphs to be shown toghether (only one at time shows up) side by side. Sometime the project also gets stuck in “HardFault_Handler”. I’d like to know if there is any problem with the structure of my project as I though it. I paid attention to all the priority and stack problems with Cortex M4, and I think the code is ok from this point of view, but maybe I’m still missing something. Flags are set and windows are created/deleted into callbacks in TestGuiBigDLG.c emWin file. Thank you!
#define Background_Task_PRIO    ( tskIDLE_PRIORITY  + 10 )
#define Background_Task_STACK   ( 512 )
#define Demo_Task_PRIO          ( tskIDLE_PRIORITY  + 9 )
#define Demo_Task_STACK         ( 3048 )
#define Demo_Task_PRIO2          ( tskIDLE_PRIORITY  + 8 )
#define Demo_Task_STACK2         ( 512 )

xTaskHandle                   Task_Handle;
xTaskHandle                   Demo_Handle;
xTaskHandle                   Demo_Handle2;

int main(void){ 
 STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_GPIO); 
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);

    TIM_Config();
    EnableTimerInterrupt();
    IOE_Config();
Demo_GyroConfig();
  Gyro_SimpleCalibration(Gyro1);
    
  /* Create demo task */
  xTaskCreate(Background_Task1,
              (signed char const*)"BK_GND",
              Background_Task_STACK,
              NULL,
              Background_Task_PRIO,
              &Task_Handle);
                            
  /* Start the FreeRTOS scheduler */
  vTaskStartScheduler();
    

    while(1){
   }
}






void TIM_Config(void)
{
TMD_STM32F4_TIMER_Init(TIM1, 5000-1, 16800-1);          
TMD_STM32F4_TIMER_Start(TIM1);
TMD_STM32F4_TIMER_enableIT_Update(TIM1);
}

void EnableTimerInterrupt()
{
    
nvicStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); 
    nvicStructure.NVIC_IRQChannelPreemptionPriority = 15;
    nvicStructure.NVIC_IRQChannelSubPriority = 0;
    nvicStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&nvicStructure);
}


static void Background_Task1(void * pvParameters)
{  
  LowLevel_Init();
  GUI_Init();
    GUI_SelectLayer(1); 
  
  /* Launch Touchscreen Timer */
  TouchScreenTimer = xTimerCreate ("Timer", 50, pdTRUE, ( void * ) 1, vTimerCallback );
  
  if( TouchScreenTimer != NULL )
  {
    if( xTimerStart( TouchScreenTimer, 0 ) != pdPASS )
    {
      /* The timer could not be set into the Active state. */
    }
  }
    
    
    xTaskCreate(Background_Task2,
              (signed char const*)"BK_GND",
              Demo_Task_STACK2,
              NULL,
              Demo_Task_PRIO2,
              &Demo_Handle2);
    
    
  xTaskCreate(Background_Task3,
              (signed char const*)"BK_GND",
              Demo_Task_STACK,
              NULL,
              Demo_Task_PRIO,
              &Demo_Handle);

    CreateTestGuiBig();
    
      while(1) { GUI_Delay(10);
        }
}

static void Background_Task2(void * pvParameters)
{
    
  while(1) { 
        if((Graphflag==1)||(Graphflag==2)){
                GRAPH_DATA_YT_AddValue(hData1, 60*ValLED3);
        }
    vTaskDelay(1);
        }
}



static void Background_Task3(void * pvParameters)
{
  while(1) { 
        Demo_GyroReadAngRate(Buffer1);

  Buffer1[0] = (int8_t)Buffer1[0]- (int8_t)Gyro1[0];
  Buffer1[1] = (int8_t)Buffer1[1] - (int8_t)Gyro1[1];
  
  /* Update autoreload and capture compare registers value*/
  Xval1 = ABS((int8_t)(Buffer1[0]));
  Yval1 = ABS((int8_t)(Buffer1[1])); 
        
        if((IMUflag==1)||(IMUflag==2)){
                GRAPH_DATA_YT_AddValue(hData2, Xval1 );
                GRAPH_DATA_YT_AddValue(hData3, Yval1 );  }

    vTaskDelay(1);
        }
}

FreeRTOS and emWin on STM32F4

Update: inverting the priorities of the 2 graph tasks seems to improve a little bit the situation..

FreeRTOS and emWin on STM32F4

I’ve never used emWin so can’t really comment on that. The interrupt priorities look ok (are you using a recent FreeRTOS version with configASSERT() defined?). However it does look like both tasks are calling GRAPHDATAYT_AddValue – is that function thread safe or do you need to add some kind of mutual exclusion (semaphore, etc.)? Regards.

FreeRTOS and emWin on STM32F4

Thanks for the support! I’m using FreeRTOS 7.1.1 and ConfigAssert() is defined. What do you mean with thread safe? Sorry but I’m a very beginner with RTOS in general. If you’re asking whether the function makes some kind of control or not, I’m afraid the answer in no. Or at least emWin reference manual doesn’t even talk about these kind of problems. How could I add a sort of control?

FreeRTOS and emWin on STM32F4

If you are using FreeRTOS V7.6.0 or higher then configASSERT() will automatically check the interrupt priorities. GRAPHDATAYTAddValue() is being called from more than one task. If it is accessing a shared resource (memory, C structure, peripheral, etc.) then calling it from more than one task risks the resource becoming corrupted. This can happen if, for example, one task is half way through updating the resource while the other that is reading from the resource. If this sort of corruption can happen then GRAPHDATAYTAddValue() is not thread safe, and you must take steps to ensure it can only be accessed by one task at a time. That can be achieved by protecting the resource with a mutex (so a task has to first obtain the mutex before it is allowed to update the resource, then give the mutex back when it has finished its update), or by locking the scheduler while the resource is in an inconsistent state (so not other task can be switched in and access the resource until it is once again in a consistent state). Regards.

FreeRTOS and emWin on STM32F4

Very clear explanation, thank you! I managed to add a mutex, just to be sure, but that didn’t resolve my problem with having both graphs running at the same time. Moreover, when I get a freeze it’s always when I close one window, so I don’t think that what you said was the real problem.