JorgeF 0 Report post Posted December 1, 2012 (edited) Hi In a project with 4 tasks, where 2 are free running with the same priority and the other two run in function of semaphores, I noticed the following behaviour. // Create tasks // LEDs 1 and 2 blinking at 2Hz in oposition (phase = 180º) SysCreateTask(hTaskLED1,4,Task_LED1); // Free run (LED1 follows LEDState) SysCreateTask(hTaskLED2,4,Task_LED2); // Free run (LED1 follows not LEDState) // LED 3 and 4 blink at 1Hz in quadrature ( phase = 90º) SysCreateTask(hTaskLED3,4,Task_LED3); // Wait Semaphore (LEDState 0->1) SysCreateTask(hTaskLED4,4,Task_LED4); // Wait Semaphore (LEDState 1->0) // LEDState variable and the signaling of the semaphores is all handled in the ISR ***** Full project attached.***** If the priority of tasks LED3 and LED4 are the same or higger than the priority of tasks LED1 and LED2 everything runs as expected and the all 4 LEDs flash acording to the program. Even if one of Task LED1 and LED2 or both are not started things work as expected. If the priority of tasks LED3 and LED4 is lower than the priority of tasks LED1 and LED2, tasks LED3 and LED4 still execute and LEDs 3 and 4 flash at 1Hz but in synch instead of in quadrature (not acording to the signaling of the semaphores). I was expecting that tasks LED3 and LED4 will be stalled (never run) due to the higher priority of the free running tasks. Is this some error of mine or there is a bug with the round robin algorithm that cycles the ready tasks with same priority. ? Best regards Jorge NOVO_Priorities_Sem_ISR.zip Edited December 1, 2012 by JorgeF Quote Share this post Link to post Share on other sites
JorgeF 0 Report post Posted December 2, 2012 (edited) Hi Quoting from another thread Your Novo problem is a good one. I have it running on my EasyPIC5 board. It says in the Novo source that the next task can be overridden by priority change or waiting task wakeup. Maybe the last part has something to do with it (waiting task wakeup). For sure it has something to do with the tasks being awaken from the semaphores. Of course the "next task" can be overrriden by a priority change. The "ready list" must be reorganized when priorities are changed so the head of the ready list can change. Also if a task is woken up and inserted in the ready list it can be inserted at the head if its priority is >= than that of the previous head. But waking up a task and inserting it ahead of another with higger priority seems a bit odd. And there is still the side efect that both low priority tasks (LED3 and LED4) run in synch when this happens. Each semaphore is signaled at about 1Hz rate and in an alternate fashion. There is about 1/2 second time gap betwen each semaphore signaling, As we have the tasks for LED1 and 2 alternating at a high rate, there is plenty of yielding betwen each task wake up event, how do the LED 3 and 4 flash in synch after beeing signaled in quadrature oposition (see interrupt code). It looks like the first of tasks LED3 or 4 wakes up and gets stalled at the end of the ready queue due to its low priority, but when the second wakes up the run task pointer gets messed. I have to do some more testing and reviewing of the NOVO source code. But so far I suspect that the run task pointer (ready queue head) skids from the second (ready queue order) high priority task (say LED2) to the just inserted low priority (say LED4), then the two low priority tasks get executed in a row and only then the run task pointer rolls back to the first high priority task. If the just awaken task gets inserted in front of the other tasks of the same priority (a common practice in RTOSs) this would mean skiding from second to third task in ready queue. EDIT: Corrected quadrature to oposition. The quadrature only applies to the output not to the semaphore signaling. Best regards Jorge Edited December 3, 2012 by JorgeF Quote Share this post Link to post Share on other sites
Dave 0 Report post Posted December 3, 2012 Hi Quoting from another thread Your Novo problem is a good one. I have it running on my EasyPIC5 board. It says in the Novo source that the next task can be overridden by priority change or waiting task wakeup. Maybe the last part has something to do with it (waiting task wakeup). For sure it has something to do with the tasks being awaken from the semaphores. Of course the "next task" can be overrriden by a priority change. The "ready list" must be reorganized when priorities are changed so the head of the ready list can change. Also if a task is woken up and inserted in the ready list it can be inserted at the head if its priority is >= than that of the previous head. But waking up a task and inserting it ahead of another with higger priority seems a bit odd. ... Something does seem to be wrong here, but I'm not sure what it is yet. Regards Dave Quote Share this post Link to post Share on other sites
Dave 0 Report post Posted December 4, 2012 JorgeF, Thanks for a fine example of code that failed. Hi Quoting from another thread Something does seem to be wrong here, but I'm not sure what it is yet. Regards Dave The following function has the error corrected that caused this problem - incorrect capture of the max priority task when adding a task to the run queue. void SysiAddToRunQueue( TASK_HANDLE hTask ) { TASK_HANDLE pos = RUN_QUEUE_HEAD; TASK_HANDLE nextPos; BYTE priority = GetTaskPriority( hTask ); BYTE maxPriority = priority; while( 1 ) { nextPos = GetNextTask( pos ); // move onto next if( nextPos == RUN_QUEUE_HEAD ) // end reached break; // exit with pos = node just before end // when priority is less than task to add we have found insertion point BYTE nextPriority = GetTaskPriority( nextPos ); if( nextPriority < priority ) break; else if( nextPriority > maxPriority ) // capture next priority maxPriority = nextPriority; pos = nextPos; } // merge node into queue SetPrevTask( hTask, pos ); SetNextTask( hTask, nextPos ); SetNextTask( pos, hTask ); SetPrevTask( nextPos, hTask ); // if task inserted at run queue head then it must be the one to run next if( pos == RUN_QUEUE_HEAD ) scheduler.os_hNextTaskActive = hTask; // if task has max priority, then it will be the new last in the run line if( priority == maxPriority ) scheduler.os_hTaskLastHp = hTask; SetTaskStatusBit( hTask, TS_IN_RUN_Q ); } You will need to update this function in novo.c and rebuild the require Novo RTOS library. Let me know if this fixes your issue. Regards Dave Quote Share this post Link to post Share on other sites
JorgeF 0 Report post Posted December 4, 2012 Hi Dave You beated me to this one, by a couple of hours. I already had my spotlights on this function, but hadn't pinpointed the exact spot yet. Thanks for the support. I'll report back as soon as I finish my tests, with this project and another variation of it that I alraedy had in place. Best regards Jorge Quote Share this post Link to post Share on other sites
JorgeF 0 Report post Posted December 5, 2012 (edited) Hi guys After rebuilding the lib (novolib_pic16t6e4ts2.lib) used by the test projects and several rebuilds with different relative priorities for the various tasks everything works as expected. So I'm glad to say ... Thanks Dave its SOLVED Next step is to rebuilding all the libs, before I mess something with a mix of corrected and uncorrected libs. Attached are the two test projects. One is the same project used to show the bug and the other is a variation with semaphores for Tasks LED3 and LED4 being signaled by Tasks LED1 and LED2, instead of being signaled by the ISR. This makes task LED3 dependent of Task LED1 and Task LED4 dependent on Task LED2. EDIT: Tested with PIC18 also, as expected, no issues. Best regards Jorge Test_Priorities_SemISR.zip Test_Priorities_SemTask.zip Edited December 7, 2012 by JorgeF Quote Share this post Link to post Share on other sites