-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add NetworkInterface.c for TMS320F2838x #1052
Conversation
@adrien-cardinale , thank you for this PR. Could you write the text "/bot run formatting" (without the quotes) and send it as a comment. The source code will be formatted to the FreeRTOS standard. After that you can do a pull on your own PR to get the same formatting on your local repo. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @adrien-cardinale , I see that you already made changes after my more informal review on the forum.
In this review a few more proposals that should help making it more efficient.
Also I am proposing to think about the 2 streams: TX packets that have been sent, and RX packets that have been received.
|
||
uint32_t ret = Ethernet_sendPacket(emac_handle, &pktDesc); | ||
|
||
if(ret == 0){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why you test for '0'? What does that mean? Success/failure?
uint32_t ret = Ethernet_sendPacket(emac_handle, &pktDesc); | ||
|
||
if(ret == 0){ | ||
vReleaseNetworkBufferAndDescriptor(pxDescriptor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before an Output function can release a packet buffer, you must test the value of xReleaseAfterSend
. If it is true, you can (must) release it after use.
In a system without zero-copy, xReleaseAfterSend
will usually be false, which means that the Output routine may not release it.
} | ||
|
||
if(xReleaseAfterSend != pdFALSE){ | ||
pxDescriptor->pucEthernetBuffer = NULL; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now you do test xReleaseAfterSend
, which is good.
But why do you set pxDescriptor->pucEthernetBuffer
to NULL?
This may be a pointer, allocated with pvPortMalloc()
. When you put it to NULL, you will get into trouble.
|
||
if(xReleaseAfterSend != pdFALSE){ | ||
pxDescriptor->pucEthernetBuffer = NULL; | ||
vReleaseNetworkBufferAndDescriptor(pxDescriptor); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case when if(ret == 0)
, you have already called vReleaseNetworkBufferAndDescriptor()
. It would cause an erro to call it again.
&( ulISREvents ), | ||
portMAX_DELAY ); | ||
if((ulISREvents & EMAC_IF_RX_EVENT) != 0){ | ||
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETHERNET_MAX_PACKET_LENGTH, 0 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you are handling a EMAC_IF_RX_EVENT
, meaning that a packet has been received. Wouldn't you check the validity of pPktDescGlobal
here, see if validLength
is within range and so?
Not need to copy ETHERNET_MAX_PACKET_LENGTH
bytes, that would be a waste of time.
Also I wouldn't create a packet buffer before calling eConsiderFrameForProcessing()
and FreeRTOS_MatchingEndpoint()
: both functions might fail.
Have a look at this:
if( valid_packet( pPktDescGlobal )
{
BaseType_t xWasAccepted = pdFALSE;
/* Check if we should handle this packet. */
if( eConsiderFrameForProcessing( pPktDescGlobal->dataBuffer ) == eProcessBuffer )
{
/* Find the proper endpoint. */
NetworkEndPoint_t * pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pPktDescGlobal->dataBuffer );
if( pxEndPoint != NULL )
{
NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( pPktDescGlobal->validLength, 0 );
if( pxBufferDescriptor != NULL )
{
memcpy( pxBufferDescriptor->pucEthernetBuffer, pPktDescGlobal->dataBuffer, pPktDescGlobal->validLength );
pxBufferDescriptor->xDataLength = pPktDescGlobal->validLength;
pxBufferDescriptor->pxEndPoint = pxEndPoint;
xRxEvent.eEventType = eNetworkRxEvent;
xRxEvent.pvData = ( void * ) pxBufferDescriptor;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdTRUE )
{
xWasAccepted = pdTRUE;
}
else
{
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
}
}
}
}
if( xWasAccepted == pdTRUE )
{
iptraceNETWORK_INTERFACE_RECEIVE();
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
}
In other words, do not call pxGetNetworkBufferWithDescriptor()
until you are sure that it will be used.
Question: How do we make sure that pPktDescGlobal
isn't accessed before by interrupt code before we've handled the last packet?
I am thinking of adding a queue or a counting semaphore between the EMAC task and the callback functions:
Ethernet_receivePacketCallbackCustom()
Ethernet_releaseTxPacketBufferCallbackCustom()
A EMAC_IF_RX_EVENT
event means: one or more packets have been received.
A EMAC_IF_TX_EVENT
event means the one or more packets have been sent.
But while you are handling some EMAC_IF
event, the interrupt may get triggered.
EDIT
I added the test if( pxBufferDescriptor != NULL )
to my sample code here above.
} | ||
|
||
static BaseType_t prvf28388d_NetworkInterfaceOutput(NetworkInterface_t* pxInterface, NetworkBufferDescriptor_t* const pxDescriptor, BaseType_t xReleaseAfterSend){ | ||
pxGlobalDescriptor = pxDescriptor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are saving the packet buffer because prvEMACDeferredInterruptHandlerTask()
will release it later on.
Please check xReleaseAfterSend
: when false, you may not release the buffer.
And also, a few lines later in this function, you are releasing pxDescriptor
, without invalidating the copy in pxGlobalDescriptor
.
/bot run formatting |
@adrien-cardinale to fix the spell check, please add the words highlighted in the spell check report to the .cSpellWords.txt. |
Hello @adrien-cardinale, how is the driver going? I wonder if there is anything we can help you with? Is there anything unclear? |
Hello @htibosch , thank you for your interest and comments. I'm actually too busy at the moment to make the changes you suggested. This is why I wanted to publish the code as is so that it can serve as a basis for other people who would like to use the driver for the TMS320F2838x. |
@adrien-cardinale - Thanks for your efforts on this PR. To prevent stale PR's, we'll be closing this for now. Feel free to reopen when you're ready to address the comments. |
NetworkInterface.c for TMS320F2838x
Description
Add NetworkInterface.c for TMS320F2838x
Test Steps
Test with TMS320F28388d from texas instrument
Checklist:
Related Issue
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.