Skip to content

Portable layer changes #701

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/FreeRTOS_DNS_Parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@
prepareReplyDNSMessage( pxNetworkBuffer, usLength );
/* This function will fill in the eth addresses and send the packet */
vReturnEthernetFrame( pxNetworkBuffer, pdFALSE );

if( pxNewBuffer != NULL )
{
vReleaseNetworkBufferAndDescriptor( pxNewBuffer );
Expand Down
202 changes: 168 additions & 34 deletions source/portable/NetworkInterface/DriverSAM/NetworkInterface.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
/*
* FreeRTOS+TCP <DEVELOPMENT BRANCH>
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
* FreeRTOS+TCP V2.3.1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
Expand Down Expand Up @@ -40,7 +38,9 @@
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "FreeRTOS_ARP.h"
#include "FreeRTOS_Routing.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"

Expand Down Expand Up @@ -172,13 +172,22 @@ static void prvEMACHandlerTask( void * pvParameters );
/*
* Initialise the ASF GMAC driver.
*/
static BaseType_t prvGMACInit( void );
static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface );

/*
* Try to obtain an Rx packet from the hardware.
*/
static uint32_t prvEMACRxPoll( void );

static BaseType_t prvSAM_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface );
static BaseType_t prvSAM_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
NetworkBufferDescriptor_t * const pxBuffer,
BaseType_t bReleaseAfterSend );
static BaseType_t prvSAM_GetPhyLinkStatus( NetworkInterface_t * pxInterface );

NetworkInterface_t * pxSAM_FillInterfaceDescriptor( BaseType_t xEMACIndex,
NetworkInterface_t * pxInterface );

/*
* Handle transmission errors.
*/
Expand All @@ -200,11 +209,16 @@ static const uint8_t llmnr_mac_address[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC
/* The GMAC object as defined by the ASF drivers. */
static gmac_device_t gs_gmac_dev;

/* MAC address to use. */
extern const uint8_t ucMACAddress[ 6 ];

/* Holds the handle of the task used as a deferred interrupt processor. The
* handle is used so direct notifications can be sent to the task for all EMAC/DMA
* related interrupts. */
TaskHandle_t xEMACTaskHandle = NULL;

static NetworkInterface_t * pxMyInterface = NULL;

static QueueHandle_t xTxBufferQueue;
int tx_release_count[ 4 ];

Expand Down Expand Up @@ -421,20 +435,21 @@ static BaseType_t xPHY_Write( BaseType_t xAddress,
}
/*-----------------------------------------------------------*/

BaseType_t xNetworkInterfaceInitialise( void )
static BaseType_t prvSAM_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface )
{
const TickType_t x5_Seconds = 5000UL;

if( xEMACTaskHandle == NULL )
{
prvGMACInit();
prvGMACInit( pxInterface );

cache_clean_invalidate();

/* The handler task is created at the highest possible priority to
* ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );
configASSERT( xEMACTaskHandle );
pxMyInterface = pxInterface;
}

if( xTxBufferQueue == NULL )
Expand All @@ -451,14 +466,54 @@ BaseType_t xNetworkInterfaceInitialise( void )

/* When returning non-zero, the stack will become active and
* start DHCP (in configured) */
return xGetPhyLinkStatus();
return prvSAM_GetPhyLinkStatus( NULL );
}
/*-----------------------------------------------------------*/

BaseType_t xGetPhyLinkStatus( void )
#if ( ipconfigCOMPATIBLE_WITH_SINGLE != 0 )

/* Do not call the following function directly. It is there for downward compatibility.
* The function FreeRTOS_IPInit() will call it to initialice the interface and end-point
* objects. See the description in FreeRTOS_Routing.h. */
NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex,
NetworkInterface_t * pxInterface )
{
pxSAM_FillInterfaceDescriptor( xEMACIndex, pxInterface );
}

#endif /* ( ipconfigCOMPATIBLE_WITH_SINGLE != 0 ) */
/*-----------------------------------------------------------*/

NetworkInterface_t * pxSAM_FillInterfaceDescriptor( BaseType_t xEMACIndex,
NetworkInterface_t * pxInterface )
{
/* This function pxSAM_FillInterfaceDescriptor() adds a network-interface.
* Make sure that the object pointed to by 'pxInterface'
* is declared static or global, and that it will remain to exist. */

memset( pxInterface, '\0', sizeof( *pxInterface ) );
pxInterface->pcName = "GMAC"; /* Just for logging, debugging. */
pxInterface->pvArgument = ( void * ) xEMACIndex; /* Has only meaning for the driver functions. */
pxInterface->pfInitialise = prvSAM_NetworkInterfaceInitialise;
pxInterface->pfOutput = prvSAM_NetworkInterfaceOutput;
pxInterface->pfGetPhyLinkStatus = prvSAM_GetPhyLinkStatus;

return pxInterface;
}
/*-----------------------------------------------------------*/

static BaseType_t prvSAM_GetPhyLinkStatus( NetworkInterface_t * pxInterface )
{
BaseType_t xReturn;

/*_RB_ Will this parameter be used by any port? */

/*_HT_ I think it will if there are two instances of an EMAC that share
* the same driver and obviously get a different 'NetworkInterface_t'. */
/* Avoid warning about unused parameter. */
( void ) pxInterface;

/* This function returns true if the Link Status in the PHY is high. */
if( xPhyObject.ulLinkStatusMask != 0 )
{
xReturn = pdPASS;
Expand Down Expand Up @@ -494,13 +549,16 @@ static void hand_tx_errors( void )

volatile IPPacket_t * pxSendPacket;

BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
static BaseType_t prvSAM_NetworkInterfaceOutput( NetworkInterface_t * pxInterface,
NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
{
/* Do not wait too long for a free TX DMA buffer. */
const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
uint32_t ulTransmitSize;

/* Avoid warning about unused parameter. */
( void ) pxInterface;
ulTransmitSize = pxDescriptor->xDataLength;

pxSendPacket = ( IPPacket_t * ) pxDescriptor->pucEthernetBuffer;
Expand All @@ -514,6 +572,15 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript
* statement. */
do
{
if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )
{
/* The packet has been sent back to the IP-task.
* The IP-task will further handle it.
* Do not release the descriptor. */
bReleaseAfterSend = pdFALSE;
break;
}

if( xPhyObject.ulLinkStatusMask == 0ul )
{
/* Do not attempt to send packets as long as the Link Status is low. */
Expand Down Expand Up @@ -571,27 +638,64 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript
}
/*-----------------------------------------------------------*/

static BaseType_t prvGMACInit( void )
static BaseType_t prvGMACInit( NetworkInterface_t * pxInterface )
{
uint32_t ncfgr;
NetworkEndPoint_t * pxEndPoint;
BaseType_t xEntry = 1;

gmac_options_t gmac_option;

pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface );
configASSERT( pxEndPoint != NULL );

gmac_enable_management( GMAC, true );
/* Enable further GMAC maintenance. */
GMAC->GMAC_NCR |= GMAC_NCR_MPE;

memset( &gmac_option, '\0', sizeof( gmac_option ) );
gmac_option.uc_copy_all_frame = 0;
gmac_option.uc_no_boardcast = 0;
memcpy( gmac_option.uc_mac_addr, ipLOCAL_MAC_ADDRESS, sizeof( gmac_option.uc_mac_addr ) );
memcpy( gmac_option.uc_mac_addr, pxEndPoint->xMACAddress.ucBytes, sizeof( gmac_option.uc_mac_addr ) );

gs_gmac_dev.p_hw = GMAC;
gmac_dev_init( GMAC, &gs_gmac_dev, &gmac_option );

NVIC_SetPriority( GMAC_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( GMAC_IRQn );

#if ( ipconfigUSE_LLMNR == 1 )
{
gmac_set_address( GMAC, xEntry++, xLLMNR_MacAdress.ucBytes );
}
#endif /* ipconfigUSE_LLMNR */

#if ( ipconfigUSE_IPv6 != 0 )
{
NetworkEndPoint_t * pxEndPoint;
#if ( ipconfigUSE_LLMNR == 1 )
{
gmac_set_address( GMAC, xEntry++, ( uint8_t * ) xLLMNR_MacAdressIPv6.ucBytes );
}
#endif /* ipconfigUSE_LLMNR */

for( pxEndPoint = FreeRTOS_FirstEndPoint( pxMyInterface );
pxEndPoint != NULL;
pxEndPoint = FreeRTOS_NextEndPoint( pxMyInterface, pxEndPoint ) )
{
if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED )
{
uint8_t ucMACAddress[ 6 ] = { 0x33, 0x33, 0xff, 0, 0, 0 };

ucMACAddress[ 3 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ];
ucMACAddress[ 4 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ];
ucMACAddress[ 5 ] = pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ];
gmac_set_address( GMAC, xEntry++, ucMACAddress );
}
}
}
#endif /* ipconfigUSE_IPv6 */

{
/* Set MDC clock divider. */
gmac_set_mdc_clock( GMAC, sysclk_get_cpu_hz() );
Expand Down Expand Up @@ -798,6 +902,8 @@ static uint32_t prvEMACRxPoll( void )
#endif /* ipconfigZERO_COPY_RX_DRIVER */

pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount;
pxNextNetworkBufferDescriptor->pxInterface = pxMyInterface;
pxNextNetworkBufferDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer );
xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor;

/* Send the descriptor to the IP task for processing. */
Expand All @@ -820,6 +926,54 @@ static uint32_t prvEMACRxPoll( void )
}
/*-----------------------------------------------------------*/

volatile UBaseType_t uxLastMinBufferCount = 0;
#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
volatile UBaseType_t uxLastMinQueueSpace;
#endif
volatile UBaseType_t uxCurrentSemCount;
volatile UBaseType_t uxLowestSemCount;

void vCheckBuffersAndQueue( void )
{
static UBaseType_t uxCurrentCount;

#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
uxCurrentCount = uxGetMinimumIPQueueSpace();

if( uxLastMinQueueSpace != uxCurrentCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinQueueSpace = uxCurrentCount;
FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) );
}
}
#endif /* ipconfigCHECK_IP_QUEUE_SPACE */
uxCurrentCount = uxGetMinimumFreeNetworkBuffers();

if( uxLastMinBufferCount != uxCurrentCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
}

if( xTXDescriptorSemaphore != NULL )
{
uxCurrentSemCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );

if( uxLowestSemCount > uxCurrentSemCount )
{
uxLowestSemCount = uxCurrentSemCount;
FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
}
}
}
/*-----------------------------------------------------------*/

extern uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * NETWORK_BUFFER_SIZE ];
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
Expand All @@ -840,7 +994,6 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB
static void prvEMACHandlerTask( void * pvParameters )
{
UBaseType_t uxCount;
UBaseType_t uxLowestSemCount = 0;

#if ( ipconfigZERO_COPY_TX_DRIVER != 0 )
NetworkBufferDescriptor_t * pxBuffer;
Expand All @@ -858,26 +1011,7 @@ static void prvEMACHandlerTask( void * pvParameters )
for( ; ; )
{
xResult = 0;

#if ( ipconfigHAS_PRINTF != 0 )
{
/* Call a function that monitors resources: the amount of free network
* buffers and the amount of free space on the heap. See FreeRTOS_IP.c
* for more detailed comments. */
vPrintResourceStats();

if( xTXDescriptorSemaphore != NULL )
{
UBaseType_t uxCurrentSemCount = uxSemaphoreGetCount( xTXDescriptorSemaphore );

if( uxLowestSemCount > uxCurrentSemCount )
{
uxLowestSemCount = uxCurrentSemCount;
FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) );
}
}
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
vCheckBuffersAndQueue();

if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 )
{
Expand Down
Loading