heinbali01 wrote on Saturday, January 27, 2018:
Hi David,
To summarise your two approaches:
FIRST case :
void Interrupt_handler()
{
char cC;
cC = LL_USART_ReceiveData(Instance);
xQueueSendFromISR(xQueueUartRx, &cC, NULL);
vTaskNotifyGiveFromISR(uartExtTaskHandle, NULL);
}
void uartExt_task(void const* argument)
{
char cChar;
while(true)
{
if (xQueueReceive(xQueueUartRx, &cChar, 0))
{
// do somethings
}
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}
}
SECOND case :
void Interrupt_handler()
{
portCHAR cC;
cC = LL_USART_ReceiveData8(USART6);
xQueueSendFromISR(xQueueUartRx,&cC, NULL);
}
void Task_for_receiving()
{
char Ccar;
for (;;)
{
if (xQueueReceive( xQueueUartRx,&Ccar, portMAX_DELAY ) == pdTRUE)
{
// do somethings
}
}
}
The second approach looks better to me.
In the first approach you are using two wake-up (or notify) mechanisms: both a message queue and a task notification. One method is enough.
Note that the second approach is ok for a terminal driver that receives key strokes or so.
When the USART is exchanging big amounts of data, it is worth using multiple DMA-buffers. Only when a buffer is full, or when no more data are expected, you send a buffer to the user. After reading it, the user will have to pass back the buffer to the driver.
Personally, I like to use circular buffers (see stream_buffer.c), where the driver may write and the user (a single user only) may read from it. This can also be combined with the task-notify mechanism:
void Interrupt_handler()
{
char cC;
BaseType_t xSwitchRequired = pdFALSE;
cC = LL_USART_ReceiveData( Instance );
addByte (&xCircularBuffer, cC);
vTaskNotifyGiveFromISR( uartExtTaskHandle, &( xSwitchRequired ) );
/* Switch context if needed: */
portYIELD_FROM_ISR( xSwitchRequired );
}
void Task_for_receiving(void const* argument)
{
char pcBuffer[ 128 ];
int iCount;
while(true)
{
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
/* When waking up, 1 or more bytes have been placed in the
circular buffer. Read them in blocks: */
for( ;; )
{
iCount = readBytes ( &xCircularBuffer, pcBuffer, sizeof pcBuffer );
if( iCount <= 0 )
{
break;
}
// do somethings
}
}
}
Note also that I added a call to portYIELD_FROM_ISR()
, to cause a context-switch.