Hi, This is my first project with RTOS. I readed a lot of docummentation ant tried some examples so now want starts my own project.
Ofcourse i’m starting from example project as base: [ble_app_server](esp-idf/examples/bluetooth/bluedroid/ble/ble_spp_server at b0150615dff529662772a60dcb57d5b559f480e2 · espressif/esp-idf (github.com))
As i readed, I should firstly plan everything and than write code. So i would ask for help with planning, that it could be optimal use of communication objects like mutexes, queues, task notifications, etc.
My project is RF receiver with one relay output, one microswitch input, one LED output, EEprom, independent RF module and BLE stack for transmision configuration data
I do not take into account in this analysis bluetooth communication, since it will be independent from other tasks (only get and put data from/to eeprom via ble).
- When push button in receiver and transmit from RF transmitter, it saves transmitter to eeprom.
- When receive correct signal from transmitter, check if it is registered in eeprom and turn on Output relay for specified time.
I think that my project needs 8 tasks:
- Task_1 (ISR) for serve data input stream from RF module - data comes asynchronously (PWM coding). Restarts buffer if frame error detected. When consistent frame detected, trigger Task_2 (data analise),
- Task_2 for analise received data (if triggered), put it into structure and trigger Task_3 if data correct (detected correct flag, CRC, etc.).
- Task_3 for checking eeprom for specific data. If flag_1=0 (microswitch depressed - see pt. 5) AND specific data found, trigger Task_4. If flag_1=0 (microswitch depressed - see pt. 5) AND specific data not found, do nothing more. If flag_1=1 (microswitch pressed - see pt.5) trigger Task_6 (does not matter if specific data found or not).
- Task_4 for service relay output on/off (or trigger ON for some fixed time - also can trigger Task_7 that counts time)
- Task_5 for serve one input for microswitch. If press detected, set flag_1. If depressed, clear flag_1.
- Task_6 for checking free record in eeprom and write data to it.
- Task_7 for counting time if Task_4 triggers output ON for specified time.
- Task_8 for driving LED (blinking slow, blinking fast, ON or OFF)
Now, i need communication between tasks (and there i’m not sure how to do it):
- Queue_1 for data collected by Task_1. Data should be received by Task_2, but only, when there is whole frame received in Task_1, not single byte, so i’m not sure… or meaby Task_2 should receive each byte-by-byte from Task_1 and collect it in internal buffer? But what if frame will be inconsistient in the middle of receiving and buffer will be cleared in Task_1. Can it send notification to Task_2 to clear his buffer?
- Queue_2 for data structured and sending by Task_2 and received by Task_3
- Queue_3 for sending data by Task_3 and receivig by Task_6 (data for writing to EEPROM). Data sended are the same data that was received from Queue_2.
- Now should i use mutexes or TaskNotifications rather? I readed that task notifications are lighter and can only notify from exactly Task_x to exactly Task_y. Also can send from ISR (my Task_1). I think that can be usable in my project. So should i use it or rather semaphores and/or mutexes?
I need it for:
- signaling of microswitch pressing/depressing (that, what i named “flag_1” in tasks planing). Sending from Task_5 to Task_3.
- sending LED action_id for Task_8 (blinking slow / blinking fast / on / off). It can be sended from some tasks but only to Task_8 (e.g from Task_5 - microswitcg pressed/depressed or from Task_4 (output ON/OFF) or from Task_7 (output ON time ends - OFF).
- signaling from Task_1 to Task_2 that data is corrupted and Task_2 must clear receiving buffer. Or meaby better signal that there are whole data in buffer for receiving by Task_2? Is it possible to not receiving from queue until notification from Task_1 occures.
- Task_2 sending notification to Task_3 that there is structured data in queue or it is not necessery, because Task_3 can be set to work only when data is in queue?
- Task_4 sends notification to Task_7 that have to count.
- Task_7 sends notification to Task_4 that it must output OFF.
How can it be done that Task_n receives data from buffer only when there are whole data sended by Task_x, not each byte? Or meaby always Task_n should receive byte-by-byte? I found something like uxQueueMessagesWaiting() so Task_n can check it and decide if reading or not yet? What is the best practise?
There is xTicksToWait parameter. “Block time – the maximum amount of time that the
task will remain in the Blocked state to wait for data to be available.”
xStatus = xQueueReceive( xQueue, &lReceivedValue, xTicksToWait );
Can I set it that task will be block all the time except when data is available in buffer?
I don’t see “vTaskStartScheduler();” in my example project (in ble_server_demo.c). Why? Where is it?
Conclusion. I used:
- 8 tasks
- 3 Queues
- a lot of notifications
I’m afraid I haven’t completely switched my mindset yet from bare-metal to RTOS way.