Skip to content
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

Closed
wants to merge 4 commits into from

Conversation

adrien-cardinale
Copy link

@adrien-cardinale adrien-cardinale commented Dec 1, 2023

NetworkInterface.c for TMS320F2838x

Description

Add NetworkInterface.c for TMS320F2838x

Test Steps

Test with TMS320F28388d from texas instrument

Checklist:

  • I have tested my changes. No regression in existing tests.
  • I have modified and/or added unit-tests to cover the code changes in this Pull Request.

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.

@adrien-cardinale adrien-cardinale requested a review from a team as a code owner December 1, 2023 09:28
@htibosch
Copy link
Contributor

htibosch commented Dec 2, 2023

@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.

Copy link
Contributor

@htibosch htibosch left a 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){
Copy link
Contributor

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);
Copy link
Contributor

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;
Copy link
Contributor

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);
Copy link
Contributor

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 );
Copy link
Contributor

@htibosch htibosch Dec 2, 2023

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;
Copy link
Contributor

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.

@adrien-cardinale
Copy link
Author

/bot run formatting

@AniruddhaKanhere
Copy link
Member

@adrien-cardinale to fix the spell check, please add the words highlighted in the spell check report to the .cSpellWords.txt.

@htibosch
Copy link
Contributor

Hello @adrien-cardinale, how is the driver going? I wonder if there is anything we can help you with? Is there anything unclear?
Or are you too busy to get on with it?

@adrien-cardinale
Copy link
Author

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.

@amazonKamath
Copy link
Member

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants