wait for a signal

hi, I have an application that run under an operating system wich implements the following feature: -———————- 2.4.1. Signals Signals represent the simplest and fastest form of task communication. These can always be used when a pure task synchronization is required without data exchange. Each active task contains its own signal flag with which the following operations can be executed: Wait for a signal Send signal Clear signal The task handle of the receiver task is used for identifying the signals for the individual operations. 2.4.1.1. Wait for a Signal Each task can wait for its signal flag (system function "os_wait_signal" and "os_wait"). It waits until its signal flag is set by another task (system function "os_send_signal"). After a signal is received, the waiting task clears its signal flag again and enters the task state READY or RUNNING, depending on priority relationships. If the signal flag is already set when the task calls the wait function (when the signal flag was previously set by another task), then it immediately receives the signal. The task does not first enter the WAIT state (BLOCKED). The waiting time for a signal can be restricted. If the specified time has expired without receiving the signal, the waiting task is made READY again with the return status "time-out" (see system function "os_wait_signal" and "os_wait"). 2.4.1.2. Send Signal Each task and each interrupt procedure can set the signal flag of any other task (send a signal to this task). Only one signal which has been sent can be stored per task (signal flag). As long as a task has not received a signal, each additional signal sent is lost. 2.4.1.3. Clear Signal A task can clear the signal flag of any other task (even it’s own). This allows defined signal states in the system at any time. -———————- Do you thing it will be possible to develop the same feature with FRTOS? If yes, how can I do? Thanks in advance

wait for a signal

I think you could just use the existing binary semaphore of mutex implementation. Its called a semaphore rather than signal but in effect does the same thing. The binary semaphore is good as a pure synchronization mechanism as it does not actually pass any data and as it does not use priority inheritance (unlike the mutex) it can be a one way communication if you like.  For example, an interrupt can "signal" a task by using the SemaphoreGiveFromISR() function. A task can block on a "signal" by using the SeamphoreTake() function and if the signal is already there is will not block but just return immediately.

wait for a signal

Thank you Dave. Your idea is pretty good. I’m afraid that it’s difficult to implement this feature: as you suggest the signal is sent is sent to semaphore, while in the other OS the signal is sent to the task. So I have to assign one semaphore to only one task. I tought that I can declare an array of configMAX_NUM_TASK semaphores. When a task is going to be in wait assign its Handle to a semaphore. When an interrupt "signal" a task, I search the Handle in the array and if I find it I use SemaphoreTake for that semaphore. Instead, if the task for wich I send the signal is not waiting, assign the Handle to semaphore and when the task try to go in waiting, search its handle inside the array and if it found it don’t wait. So, what do you think about this idea? Have you got some more suggestions about this thread?

wait for a signal

Starting from Dave’s suggestion, I put down this piece of code: static xSemaphoreHandle xSemphrList[configMAX_NUM_TASK]; unsigned portBASE_TYPE usTaskWait(unsigned portBASE_TYPE event_selector, unsigned portBASE_TYPE timeout) {     unsigned portBASE_TYPE retval=1;         if( (event_selector & W_SIG) == W_SIG )     {         unsigned char i=pxCurrentTCB->uxTCBNumber;         unsigned portLONG timeFirst;         unsigned portLONG timeAfter;                  portDISABLE_INTERRUPTS();            if(xSemphrList[i]==NULL)         {             vSemaphoreCreateBinary(xSemphrList[i]);         }         timeFirst=usTaskGetTickElapsed();         if( xSemphrList[i] != NULL )         {                        xSemaphoreTake( xSemphrList[i], timeout );         }         timeAfter=usTaskGetTickElapsed();         portENABLE_INTERRUPTS();         if( (timeFirst+timeout) <= timeAfter )             retval=E_TMO;         else             retval=E_SIG;     }     else     {         if( (event_selector & W_TMO) == W_TMO )         {             vTaskDelay(timeout);             retval=E_TMO;         }     }     return retval; } /*! brief Manda un segnale ad un task La funzione manda un segnale ad un task param    *task        Handle del task a cui deve essere mandato il segnale return                1 se l’operazione e’ andata a buon fine, 0 se il puntatore                        del TCB fornito e’ NULL */ unsigned portBASE_TYPE usTaskSendSignal(void * task) {     tskTCB *pxUnblockedTCB;     unsigned portBASE_TYPE retval=pdFALSE;     if(task!=NULL)     {         unsigned char i;                 portDISABLE_INTERRUPTS();         pxUnblockedTCB=(tskTCB *)task;         i=pxUnblockedTCB->uxTCBNumber;         if(xSemphrList[i]==NULL)         {             vSemaphoreCreateBinary(xSemphrList[i]);         }         if( xSemphrList[i] != NULL )         {             retval=xSemaphoreGive(xSemphrList[i]);         }         portENABLE_INTERRUPTS();     }     return retval; } /*! brief Manda un segnale ad un task La funzione manda un segnale ad un task param    *task        Handle del task a cui deve essere mandato il segnale return                1 se l’operazione e’ andata a buon fine, 0 se il puntatore                        del TCB fornito e’ NULL */ unsigned portBASE_TYPE usTaskSendSignalFromISR(void * task) {     tskTCB *pxUnblockedTCB;     unsigned portBASE_TYPE retval=pdFALSE;     if(task!=NULL)     {         unsigned char i;                 portDISABLE_INTERRUPTS();         pxUnblockedTCB=(tskTCB *)task;         i=pxUnblockedTCB->uxTCBNumber;         if(xSemphrList[i]==NULL)         {             vSemaphoreCreateBinary(xSemphrList[i]);         }         if( xSemphrList[i] != NULL )         {             retval=xSemaphoreGiveFromISR(xSemphrList[i],pdFALSE);         }         portENABLE_INTERRUPTS();     }     return retval; } /*! brief Cancella un segnale ad un task La funzione cancella un segnale ad un task param    *task        Handle del task a cui deve essere mandato il segnale return                1 se l’operazione e’ andata a buon fine, 0 se il puntatore                        del TCB fornito e’ NULL */ unsigned portBASE_TYPE usTaskClearSignal(void * task) {     unsigned portBASE_TYPE retval=1;     tskTCB * pxUnblockedTCB;     if(task!=NULL)     {         unsigned char i;         portDISABLE_INTERRUPTS();         pxUnblockedTCB=(tskTCB *)task;         i=pxUnblockedTCB->uxTCBNumber;                 if(xSemphrList[i]!=NULL)         {             vQueueDelete(xSemphrList[i]);             xSemphrList[i]=NULL;         }         retval=0;         portENABLE_INTERRUPTS();     }     return retval; } /*! brief Cancella un segnale ad un task La funzione cancella un segnale ad un task param    *task        Handle del task a cui deve essere mandato il segnale return                1 se l’operazione e’ andata a buon fine, 0 se il puntatore                        del TCB fornito e’ NULL */ unsigned portBASE_TYPE usTaskClearSignalFromISR(void * task) {     unsigned portBASE_TYPE retval=1;     tskTCB * pxUnblockedTCB;     if(task!=NULL)     {         unsigned char i;         portDISABLE_INTERRUPTS();         pxUnblockedTCB=(tskTCB *)task;         i=pxUnblockedTCB->uxTCBNumber;         if(xSemphrList[i]!=NULL)         {             vQueueDelete(xSemphrList[i]);             xSemphrList[i]=NULL;         }         retval=0;         portENABLE_INTERRUPTS();     }     return retval; } Is it right to use the vQueueDelete to clear signal? Even if the asynchronous serial seem to work, the synchronous serial does not. I think this could be due to the timing. Should I add a forced switch context at the end of send signal even if I can not explicitly find out in the datasheet? I have another idea: if an ISR send signal to task and the scheduler is suspended, the task is insert in the pending list. Should I write a vApplicationTickHook function that remove the task from the pending list and insert it in the ready list? In this way the task will be processed more fastly. Best regards

wait for a signal

I have not been following this thread and have only scanned the code but I would definitely say that you are using critical sections where I dont think any are needed. The queue and semaphore functions take care of the mutual exclusion of the queues themselves. I also dont think you need to ever delete a queue or semaphore but just use it to pass data. The data is transitory in the system not the queue or semaphore. To wait for a message can you not just wait on a queue with the data that is sent on the queue being the event type. This would be normal. xQueueHandle queue; xQueueCreate(); // whatever if( xQueueReceive( queue, &event, portMAX_DELAY ) ) // or what ever delay {     switch( event ) {        case W_SIG : //do something                     break;        case W_TMO : // do something                     break;     }    }

wait for a signal

Alone from your description I think you misunderstood something. To wait for a Queue/Semaphore you use xQueueReceive/xSemaphoreTake with To send to a Queue/Semaphore you use xQueueSend(FromISR)/xSemaphoreGive(FromISR) Deleting a queue means you free memory used by the queue, not "releasing" the signal As soon as data are sent to a queue the waiting tasks reads the one piece of data from the queue. If a queue already has stored data the task will return immediately and if a queue is empty it waits until the block time is reached. There is no need to release the signal manually because it is done somehow automatically. For more information refer to the API documentation on the website and the example codes for different MCUs

wait for a signal

ok. I’ve undertsand what you said. But if a queue already has stored data, I want remove this data in order to the task will not return but wait a new data on the queue. Is this possible?

wait for a signal

only while(pdPASS==xQueueReceive( queue, &var, 0 ));