orifai01 wrote on Tuesday, January 03, 2017:
Hello, I’m trying to pass received data to the TCP/IP in a deferred interrupt handler task.
I’ve implemented an ISR called xEthernetHandler as described in xTimerPendFunctionCallFromISR web page:
void xEthernetHandler( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
NVIC_ClearPendingIRQ(ETHERNET_IRQn);
if(smsc9220_RxStatusFifoLevelIrq())
{
xTimerPendFunctionCallFromISR( prvEMACDeferredInterruptHandlerTask,
NULL,
1,
&xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
}
void prvEMACDeferredInterruptHandlerTask( void * pvParameter1, uint32_t ulParameter2 )
{
NetworkBufferDescriptor_t *pxBufferDescriptor;
size_t xBytesReceived;
unsigned int index = 0;
/* Used to indicate that xSendEventStructToIPTask() is being called because
of an Ethernet receive event. */
IPStackEvent_t xRxEvent;
for( ;; )
{
/* Wait for the Ethernet MAC interrupt to indicate that another packet
has been received. The task notification is used in a similar way to a
counting semaphore to count Rx events, but is a lot more efficient than
a semaphore. */
ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
/* See how much data was received. Here it is assumed ReceiveSize() is
a peripheral driver function that returns the number of bytes in the
received Ethernet frame. */
xBytesReceived = smsc9220_recv_size();
if( xBytesReceived > 0 )
{
/* Allocate a network buffer descriptor that points to a buffer
large enough to hold the received frame. As this is the simple
rather than efficient example the received data will just be copied
into this buffer. */
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( xBytesReceived, 0 );
if( pxBufferDescriptor != NULL )
{
if(smsc9220_recv_packet((unsigned int *)pxBufferDescriptor->pucEthernetBuffer, &index))
{
printf("Packet receive failed.\n");
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
}
else
{
pxBufferDescriptor->xDataLength = xBytesReceived;
/* See if the data contained in the received Ethernet frame needs
to be processed. NOTE! It is preferable to do this in
the interrupt service routine itself, which would remove the need
to unblock this task for packets that don't need processing. */
if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer )
== eProcessBuffer )
{
/* The event about to be sent to the TCP/IP is an Rx event. */
xRxEvent.eEventType = eNetworkRxEvent;
/* pvData is used to point to the network buffer descriptor that
now references the received data. */
xRxEvent.pvData = ( void * ) pxBufferDescriptor;
/* Send the data to the TCP/IP stack. */
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{
/* The buffer could not be sent to the IP task so the buffer
must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
/* Make a call to the standard trace macro to log the
occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
}
else
{
/* The message was successfully sent to the TCP/IP stack.
Call the standard trace macro to log the occurrence. */
iptraceNETWORK_INTERFACE_RECEIVE();
}
}
else
{
/* The Ethernet frame can be dropped, but the Ethernet buffer
must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
}
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
}
}
}
I’m using BufferAllocation_2.c. ipconfigIP_TASK_PRIORITY is set to (configMAX_PRIORITIES - 1).
Two questions:
- I don’t understand why ulTaskNotifyTake() is necessary, as we already got an Ethernet MAC interrupt (that’s the reason we entered handllerTask function).
2.Althugh xTimerPendFunctionCallFromISR changes xHigherPriorityTaskWoken to be pdTRUE, prvEMACDeferredInterruptHandlerTask is not being called and all task seem to be stuck.
Thank you for your help