i777 wrote on Tuesday, March 31, 2015:
Hi,
Im running freeRTOS on AVR mega 2560. I have two tasks A and B and also global data structure let
s name it G:
A - periodic (50 Hz) and responsible for reading data form sensor through I2C and performing some algorithm. It uses configuration stored in G.
void control_task(void * pvParameters)
{
TickType_t xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
while (1)
{
vTaskDelayUntil(&xLastWakeTime, (CONTROL_PERIOD_MS / portTICK_RATE_MS));
// Read sensor
// Calibrate readings using data stored in G
// Perform algo using data stored in G
}
}
B - is responsible for communication through serial port with a PC application. Reception of each byte is done in the ISR. After receiving complete packet it`s processed in this task. Any other requests form PC between processing and trasmitting response are rejected. Some requests are read/write operations on struct G. Accessing G can occur anytime.
void serial_link_task(void * pvParameters)
{
while(1)
{
if(ready_to_process == 1)
{
ready_to_process = 0;
// Read form / write to data in G structure
// Prepare response
// Transmitt response (handeled in tx ISR)
}
}
}
Since these two tasks use global struct G it needs to be protected by a semaphore, mutex or copied into queue. I do not know which one should be used here.
Semaphore or mutex uses block time - how many ticks should wait for access. In the task A I do not want to wait for the semaphore or mutex to be obtained. It should be executed without any delay. Because it could happen that after giving the sem/mutex by task A task B takes this sem/mutex just before task A. Context switch is done and task A leaves empty handed.
if(pdTRUE == xSemaphoreTake(sem, 0)) <-- oops task B as the sem/mutex
{
// Read sensor
// Calibrate readings using data stored in G
// Perform algo
xSemaphoreGive(sem);
}
Now the only solution that is working is to combine these two tasks into one like so:
void control_and_serial_task(void * pvParameters)
{
TickType_t xLastWakeTime;
xLastWakeTime = xTaskGetTickCount();
while (1)
{
vTaskDelayUntil(&xLastWakeTime, (CONTROL_PERIOD_MS / portTICK_RATE_MS));
// Read sensor
// Calibrate readings using data stored in G
// Perform algo using data stored in G
// Read form / write to data in G structure
// Prepare response
// Transmitt response (handeled in tx ISR)
}
}
But this limits serial throughput heavily. The other way I think is to use queues somehow. Can anyone help me how to solve the problem of sharing the data between tasks A and B without delaying execution of task A ?
Sorry for my english