ggerla wrote on Thursday, January 10, 2008:
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