Problem with semaphore in FreeRTOS on ESP32
Asked yesterday
Modified yesterday
Viewed 65 times
1
I’m working on a graphic interface that uses an ESP32 alongside a Nokia 1616 LCD.
I am editing old code that someone wrote and it works correctly and it is based on FreeRTOS and I am trying to add a scrolling text to the LCD.
The tasks that should work simultaneously are Tasktimerhandle, SendDatahandle and Task1code.
The Nokia 1616 LCD works with SPI and with the function Lcd_string_english I can draw a string on LCD with a specific coordinates.
I draw the string then I wait for 125ms and during this time other tasks can be done and then the LCD is cleared and then a new string is shown on LCD shifted by 1 that makes the illusion of a scrolling text.
I can do the scrolling alone using a for
loop but some other tasks should be done, for example a prompt must be shown on above and a scrolling text in below while the user can enter a number which is shown in the middle etc.
When I try to edit the code and add a semaphore and the task for scrolling, the interface works but it seems like the task that I wrote is ignored and it doesn’t show the floating text on the LCD.
Here is the main part of my code: what might be the problem?
#ifdef FREERTOS
SemaphoreHandle_t sema_v;
SemaphoreHandle_t sema_v_1;
SemaphoreHandle_t sema_timer;
SemaphoreHandle_t sema_v_2;
void Tasktimerhandle(void *pvParameters);
void SendDatahandle(void *pvParameters);
void Task1code(void *pvParameters);
#endif
void setup()
{
#ifdef FREERTOS
.
.
.
xTaskCreatePinnedToCore(Tasktimerhandle, "Tasktimerhandle", 50000, NULL, 1 // priority
, NULL, 0); /* pin task to core 1 */
xTaskCreatePinnedToCore(Task1code, "Task1code", 50000, NULL, 0 // priority
, NULL, 1); /* pin task to core 1 */
xTaskCreatePinnedToCore(SendDatahandle, "SendDatahandle", 50000, NULL, 1 // priority
, NULL, 1); /* pin task to core 0 */
/* create binary semaphore for send signal to send to server task */
sema_v = xSemaphoreCreateCounting(3, 0);
sema_v_1 = xSemaphoreCreateCounting(3, 0);
sema_timer = xSemaphoreCreateCounting(3, 0);
sema_v_2 = xSemaphoreCreateCounting(3, 0);
#endif
#ifndef FREERTOS
.
.
.
#endif
}
void loop()
{
#ifndef FREERTOS
Keypadtimer_handle();
Wifi_check();
#else
vTaskDelete(NULL);
#endif
}
#ifdef FREERTOS
/*timer task*/
void Tasktimerhandle(void *pvParameters)
{
(void)pvParameters;
keypad_init();
Lcd_init();
Show_homepage();
Keypadtimer_init();
vTaskDelay(2000);
EE_init();
for (;;)
{
if (xSemaphoreTake(sema_timer, portMAX_DELAY) == pdTRUE)
{
.
.
.
}
}
}
#endif
/*check internet task */
void SendDatahandle(void *pvParameters)
{
(void)pvParameters;
.
.
.
bool success;
SendTo_Server_Status serverstatus;
for (;;)
{
if (xSemaphoreTake(sema_v, 300) == pdPASS)
{
xSemaphoreGive(sema_v_1);
xSemaphoreGive(sema_v_2);
EEprom_status ee;
EEprom_status ee_1;
vTaskDelay(200);
if (Birthdate[5] != 0)
{
serverstatus = SendToServer(Birthdate);
}
else
{
serverstatus = SendToServer(number);
}
birth_flag = 0;
.
.
.
xSemaphoreGive(sema_v);
}
.
.
.
}
}
void Task1code(void *pvParameters)
{
(void)pvParameters;
for (;;)
{
xSemaphoreTake(sema_v_2,portMAX_DELAY);
for (int i = 0; i < 160; i += 5)
{
Lcd_string_english("TCCO.IR", u8g2_font_timR24_tr, i, 110, WHITE, GRAY);
vTaskDelay(pdMS_TO_TICKS(125));
LCD_CLEAR_SCROLLING();
}
xSemaphoreGive(sema_v_2);
}
}
#endif
ShareCite
EditFollowFlag

13.4k22 gold badges3232 silver badges4545 bronze badges
asked yesterday
7988 bronze badges
- 1Please check the serial UART output, there is usually some clue as to the cause of a crash/reboot there. Then read about the Minimal, Reproducible Example. Start removing stuff from your code until it doesn’t crash anymore. Most likely you’ll solve it yourself this way, and if not, you’ll have a small piece of code that’ll be much easier for us to look at and check. – TypeIA yesterday
- 2Spend a lot more time describing, in detail, what functionality has to work, simultaneously. Don’t discuss the library code or the old code you also have. Just describe, in detail, what should function together and how it should function together. A design flows out of that. From there you can decide if the existing code or other libraries may be appropriate or inappropriate. I know nothing about the Nokia 1616 LCD. Talk about it. How does it work? How does a user input information? Etc. Just dumping out code like this may get a lucky hit from someone. But not likely. – jonk yesterday
- @jonk thanks for your answer . the tasks that should work simultaneously are Tasktimerhandle, SendDatahandle and Task1code. the Nokia 1616 LCD works with SPI and with the function Lcd_string_english I can draw a string on LCD with a specific coordinates. I draw the string then i wait for 125 ms and during this time other tasks can be done and then the LCD is cleared and then a new string is shown on LCD shifted by 1 that makes the illusion of a scrolling text. i try to add a design flow to original question later – salar1991 yesterday
- 1@salar1991 No, don’t tell me what routines should work simultaneously. That’s a design you already have and you know is not working. I don’t care about it, at all. Just want a clear description of what a user should see and be able to interact with, and how so. For example, you already mentioned scrolling. Does scrolling take place as though the scrolled material is a background while at the same time a prompt must stay firmly fixed in the foreground on the display while user input is also accepted?? Those kinds of details. I don’t want any info on your design. It doesn’t work. – jonk yesterday
- 1Your toy is too complicated. (1) Usually I start cutting everything except perhaps the following two tasks: (a) Nokia display task , (b) keyboard input task, (2) I try a big loop for the two tasks, (3) I crate only one semaphore so the key board would (b) first switch on the semaphore before inputting a key, put the key in a buffer and then switch off the semaphore. (4) The display task must first wait to see if semaphore is free, open the same semaphore before checking out the buffer, and if buffer has new data, display the key and then close the semaphore., … – tlfong01 yesterday
- @jonk sorry i think you didn’t understand correctly. the old code works correctly. the problem occurs when i add my code to it (the task with the scrolling text ) about your question yes a prompt must be shown on above and a scrolling text in below while the user can enter a number which is shown in the middle – salar1991 yesterday
- 1Please edit new information into your question, don’t post it in comments. Otherwise, readers have to piece together the full question from fragments. Thanks. – TonyM yesterday
- @tlfong01 thanks for your detailed answer but there are other things that should be done other than showing a key from keypad like connecting to a local WIFI and sending data, saving some data on eeprom and these functions are in tasks Tasktimerhandle and SendDatahandle. i didn’t show some stuff to make the code readable. – salar1991 yesterday
- Why are you using
xTaskCreatePinnedToCore
to start your tasks? Do you really care which core each task runs on? And your comments after eachxTaskCreatePinnedToCore
call don’t match the actual code, for example for “Tasktimerhandle” you comment “/* pin task to core 1 */” but the code passes0
, similarly for “SendDatahandle”. – brhans yesterday - You’re ‘giving’ your
sema_v_2
more than you’re ‘taking’ it. In “Task1code” you’re taking at the start of your for loop and then giving it back at the end. But you’re also giving it inside “SendDatahandle” – brhans yesterday - From your description of the behavior you want, it seems like the base problem you need to solve is that more than one task needs to access the LCD, and obviously they can’t do that simultaneously. If that’s the case, then it’s the LCD code (
LCD_string_english
) which needs a semaphore to “protect” it – putting multiple semaphores all over the tasks is not solving the problem and is unnecessarily complicating your code. – brhans yesterday - I’d suggest creating a “wrapper” for
LCD_string_english
and whatever other LCD functions you use which does something like “Take Semaphore, Do LCD Operation(s), Give Semaphore”, so that whichever task wants to talk to the LCD has to wait if any other task is already using it. Note that there’s only one semaphore used here, not one for each task. – brhans yesterday - @salar1991 I’m only interested in the external behaviors required. The external spec. I’m not interested in trying to understand an existing body of code. That’s just me, though. I’ll back away. Sorry about the trouble. – jonk yesterday
- @alar1991: (1) I understand your system is very complicated, and as you said, including: “a key from keypad, connecting to a local WIFI, sending data, saving some data on eeprom, …”, (2) But for prototyping, I still think it is a good idea to make things as simple as possible (but not simpler). (3) If you already have a working system, you can disable/uncomment unrelated tasks, and focus to the new tasks you want to develop, (4) Or you can put away you working system, and start freshly with a minimal system, to prove your concepts, … / to continue, … – tlfong01 17 hours ago
- I am not sure if you have read enough tutorials to build up knowledge and skills for your project. I would prefer the following tutorials: FreeRTOS References V0.1 2022sep04 (1) FreeRTOS Wikipedia en.wikipedia.org/wiki/FreeRTOS (2) SMP Demos for the Raspberry Pi Pico Board – FreeRTOS 2021dec freertos.org/smp-demos-for-the-raspberry-pi-pico-board.html (3) How to use FreeRTOS with the Raspberry Pi Pico (4) Part 1: Blinky Test (5) Part 2: Tasks and Queues (6) Part 3: Scheduling and Task Priorities (7) Part 4: Mutex (8) Part 5: Semaphores – tlfong01 17 hours ago
Categories: Uncategorized