Hi,
I am running a code on ESP IDE for ESP32 S3 board and WT32-SC01 Plus Touch LCD.
My lvgl code used to work fine when it was a single task and I had the main_app very simple as follow:
extern "C" void app_main(void)
{
init_lvgl_lgfx();
ui_init();
while (true)
{
lv_timer_handler(); /* let the GUI do its work */
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
Then I had to add other tasks with different rates so I decided to use xTaskCreate function. The code builds with no error and the other two tasks work properly( SD card logging and ESP-Now). However, lv_timer_handler() do not seem to be running (I have made sure that the while loop runs with the handler inside it with a ESP_LOGI(TAG, “The loop runs”)). LCD shows black screen.
TaskHandle_t FreeRTOSTIDs[3];
SemaphoreHandle_t rtTaskSemaphoreList[3];
void tRate1(void *pvParameter)
{
while (1) {
xSemaphoreTake(rtTaskSemaphoreList[1], portMAX_DELAY);
/* Set model inputs associated to subrate here */
/* Step the model for sample time for tid */
SW_step1();
/* Get model outputs here */
}
}
void tRate2(void *pvParameters)
{
while (1) {
xSemaphoreTake(rtTaskSemaphoreList[2], portMAX_DELAY);
/* Set model inputs associated to subrate here */
/* Step the model for sample time for tid */
SW_step2();
/* Get model outputs here */
}
}
void tBaseRate(void *pvParameters)
{
const TickType_t vPeriodicTaskPreiod = 10/portTICK_PERIOD_MS;
TickType_t xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
/* For debuging the base rate semaphore release. Ignore */
static int taskCounter[3] = { 0, 0, 0 };
int i;
while (1) {
/* Set model base rate here: */
vTaskDelayUntil(&xLastWakeTime, vPeriodicTaskPreiod);
for (i = 1; i < 3; i++) {
if (taskCounter[i] == 0) {
xSemaphoreGive(rtTaskSemaphoreList[i]);
}
}
taskCounter[1]++;
if (taskCounter[1] == 100) {
taskCounter[1]= 0;
}
taskCounter[2]++;
if (taskCounter[2] == 200) {
taskCounter[2]= 0;
}
/* Set model inputs associated with base rate here */
/* Step the model for base rate */
lv_timer_handler(); /* let the GUI do its work */
ESP_LOGI(TAG, "The loop runs");
/* Get model outputs here */
}
vSemaphoreDelete(rtTaskSemaphoreList[1]);
vTaskDelete(FreeRTOSTIDs[1]);
vSemaphoreDelete(rtTaskSemaphoreList[2]);
vTaskDelete(FreeRTOSTIDs[2]);
/* Delete the base-rate task */
vTaskDelete(FreeRTOSTIDs[0]);
}
extern "C" void app_main(void)
{
/* Initialize model */
init_lvgl_lgfx();
ui_init();
UBaseType_t BaseRateTaskPriority = 2;
rtTaskSemaphoreList[1] = xSemaphoreCreateBinary();
xTaskCreate(tRate1, "tRate1", STACK_SIZE, NULL, 1, &FreeRTOSTIDs[1]);
rtTaskSemaphoreList[2] = xSemaphoreCreateBinary();
xTaskCreate(tRate2, "tRate2", STACK_SIZE, NULL, 0, &FreeRTOSTIDs[2]);
xTaskCreate(tBaseRate, "tBaseRate", STACK_SIZE, NULL, BaseRateTaskPriority,&FreeRTOSTIDs[0]);
}
/* [EOF] */
I am not really sure about the difference but I have also tried “lv_task_handler()” function. No luck!
I really appreciate if anyone could help with this issue.
There is one item I can see you should probably address.
If you are using freeRTOS I believe if your app_main() function is being called by xTaskCreate() somewhere you should terminate the function with a call to vTaskDelete(), I have personally experienced much undefined behaviour if this call is ommitted!
The other item to check is whether you are still calling lv_tick_inc() function somewhere as I can not see it mentioned in your code or description. If this is not called the lv_timer_handler() routine will not function.
Yes, draw_buf, buf and buf2 are all static and global.
Yes, ESP_LOGI(TAG, "The loop runs"); entry is being called continuously.
BUT:
I put log output for lv_tick_task() and noticed that function is not called as you were concerned.
I am confused, How can lv_timer_handler() be called continuously but not lv_tick_task().
I thought every time lv_timer_handler() is called, it will call lv_tick_task() as well.
The lv_tick_inc()/lv_tick_task() function needs to be called from a periodic interrupt or a timer independently from the lv_timer_task() so the esp_timer is most likely not working… I assume the value of LV_TICK_PERIOD_MS is not set to zero also, please check.
Looking at the code carefully there may be an issue here where the variables for the timer are going out of scope as the stack is being reclaimed after the termination of app_main() function so my next thing to suggest would be to modify the timer code as follows:
Sorry for the late response and thanks for helping me again.
LV_TICK_PERIOD_MS is not set to zero and I made those variables static and still does not work.
I’ve tried to move things around and at this point I’m out of ideas.
Why you complicate this.
Primary tick is handled in lv_conf.h
/*Use a custom tick source that tells the elapsed time in milliseconds.
*It removes the need to manually update the tick with `lv_tick_inc()`)*/
#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
#endif /*LV_TICK_CUSTOM*/
And if you dont have multicore MCU, use threads for timing is waste of resources.
Simple effective way is in loop use if timer variable % num == x run period …
Thanks for your response.
I’m new to ESP32 and the concept of threads in general.
I’m just following on example I saw online for doing multi rate task operations.
I am just not undertaking why the tick function does not operate properly when defined the way I defined it.
Can you please elaborate on your “waste of resource” comment.
Also, I am using ESP IDE and not Arduino and there is no loop function. I understand I can use “while” instead but not sure if that does the exact same thing.
It is strange! I would say without seeing all the internals of the code etc. almost certainly the ESP timer is not running.
I have no experience with your hardware/software or development platform so it’s difficult to go much further for me. I can possibly do a bit more if you can you share which tools you are using, I have now download VS Code and the ESP IDF plug-in, in the hope I can get a glimpse of the ESP32 code and vendor implementation to see what is going on.
If you can tell me as much info as possible about your development setup I will try my best to duplicate your setup here (without your hardware of course) and I might be able to get a view of the big picture, which is missing for me right now.