e_bak wrote on Thursday, April 09, 2015:
Hi,
I have a strange scheduling issue with the cooperative scheduler on Cortex M3.
I have a logger task which writes onto the serial port.
I have a task which intends to test the logger task:
void taskPrintTest(void *params) { uint32_t cnt = 0; while (1) { printf("TaskName: %s, cnt: %d\n", pcTaskGetTaskName(NULL), cnt++); /* vTaskDelay(pdMS_TO_TICKS(250)); */ /* TODO look for why only "pr2" is scheduled when the delay is removed !!! */ } }
In the main() function I create 3 instances of them:
xTaskCreate( taskPrintTest, "pr0", configMINIMAL_STACK_SIZE, NULL, 3, NULL); xTaskCreate( taskPrintTest, "pr1", configMINIMAL_STACK_SIZE, NULL, 3, NULL); xTaskCreate( taskPrintTest, "pr2", configMINIMAL_STACK_SIZE, NULL, 3, NULL);
The printf() method is used to send print event to the logger task via a queue:
static void lock() { /* take mutex */ configASSERT( xSemaphoreTake(mutex, portMAX_DELAY)); /* save task handle */ taskToNotify = xTaskGetCurrentTaskHandle(); } static void release() { /* get task notification */ ulTaskNotifyTake(pdTRUE, portMAX_DELAY); /* release mutex */ configASSERT( xSemaphoreGive(mutex)); } void printf(const char * fmt, ...) { va_list va; QueueEvent event; lock(); va_start(va, fmt); vsprintf(sprintfBuf, fmt, va); va_end(va); event.type = PrintEvent; event.msg = sprintfBuf; /* write to task event queue */ configASSERT( xQueueSendToBack(queue, &event, portMAX_DELAY)); release(); }
After the event is written into the queue, the task should block at ulTaskNotifyTake(pdTRUE, portMAX_DELAY), the xTaskNotifyGive(taskToNotify) is made by the logger task.
My experience is that only one of the taskPrintTest task is getting executed. On the serial console I see messages from task “pr2” only:
…
TaskName: pr2, cnt: 297710
TaskName: pr2, cnt: 297711
TaskName: pr2, cnt: 297712
TaskName: pr2, cnt: 297713
TaskName: pr2, cnt: 297714
TaskName: pr2, cnt: 297715
…
When I enable the delay in the taskPrintTest task “vTaskDelay(pdMS_TO_TICKS(250));”, the scheduling seems to be corrected:
…
TaskName: pr2, cnt: 0
TaskName: pr0, cnt: 0
TaskName: pr1, cnt: 0
TaskName: pr2, cnt: 1
TaskName: pr0, cnt: 1
TaskName: pr1, cnt: 1
TaskName: pr2, cnt: 2
TaskName: pr0, cnt: 2
TaskName: pr1, cnt: 2
…
I think even in the first case, when there is no delay in the print loop, the scheduler should execute “pr0” and “pr1” too in a Round-Robin manner. I think the taskPrintTest task is surely gets blocked at ulTaskNotifyTake(pdTRUE, portMAX_DELAY) in the release() method, at this point the scheduler should switch into an other instance of taskPrintTest.
Is it a normal behavior? What can cause this anomaly?
(Beside the taskPrintTest tasks I have the logger task and a led blinker task, these both seems to be scheduled and working all right.)
main.c: http://pastebin.com/vPBZmB7e
LoggerTask.c: http://pastebin.com/5pB39bT2