Update version number in readiness for V10.3.0 release. Sync SVN with reviewed release candidate.

This commit is contained in:
Yuhui.Zheng 2020-02-07 20:14:50 +00:00
parent f988394e0d
commit 589dd9f149
1989 changed files with 40469 additions and 139137 deletions

View file

@ -1,411 +1,411 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
*
******************************************************************************/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
/* For an Ethernet interrupt to be able to obtain a network buffer there must
be at least this number of buffers available. */
#define baINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
/* A list of free (available) NetworkBufferDescriptor_t structures. */
static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */
static UBaseType_t uxMinimumFreeNetworkBuffers = 0u;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist
in this array. The array is not accessed directly except during initialisation,
when the xFreeBuffersList is filled (as all the buffers are free when the system
is booted). */
static NetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
/* This constant is defined as true to let FreeRTOS_TCP_IP.c know that the
network buffers have constant size, large enough to hold the biggest Ethernet
packet. No resizing will be done. */
const BaseType_t xBufferAllocFixedSize = pdTRUE;
/* The semaphore used to obtain network buffers. */
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
#if( ipconfigTCP_IP_SANITY != 0 )
static char cIsLow = pdFALSE;
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
#else
static UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
#endif /* ipconfigTCP_IP_SANITY */
static void prvShowWarnings( void );
/* The user can define their own ipconfigBUFFER_ALLOC_LOCK() and
ipconfigBUFFER_ALLOC_UNLOCK() macros, especially for use form an ISR. If these
are not defined then default them to call the normal enter/exit critical
section macros. */
#if !defined( ipconfigBUFFER_ALLOC_LOCK )
#define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0)
#define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \
UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
{
#define ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR() \
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
}
#define ipconfigBUFFER_ALLOC_LOCK() taskENTER_CRITICAL()
#define ipconfigBUFFER_ALLOC_UNLOCK() taskEXIT_CRITICAL()
#endif /* ipconfigBUFFER_ALLOC_LOCK */
/*-----------------------------------------------------------*/
#if( ipconfigTCP_IP_SANITY != 0 )
/* HT: SANITY code will be removed as soon as the library is stable
* and and ready to become public
* Function below gives information about the use of buffers */
#define WARN_LOW ( 2 )
#define WARN_HIGH ( ( 5 * ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) / 10 )
#endif /* ipconfigTCP_IP_SANITY */
/*-----------------------------------------------------------*/
#if( ipconfigTCP_IP_SANITY != 0 )
BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr )
{
return ( bIsValidNetworkDescriptor( pxDescr ) != 0 ) &&
( listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxDescr->xBufferListItem ) ) != 0 );
}
/*-----------------------------------------------------------*/
static void prvShowWarnings( void )
{
UBaseType_t uxCount = uxGetNumberOfFreeNetworkBuffers( );
if( ( ( cIsLow == 0 ) && ( uxCount <= WARN_LOW ) ) || ( ( cIsLow != 0 ) && ( uxCount >= WARN_HIGH ) ) )
{
cIsLow = !cIsLow;
FreeRTOS_debug_printf( ( "*** Warning *** %s %lu buffers left\n", cIsLow ? "only" : "now", uxCount ) );
}
}
/*-----------------------------------------------------------*/
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )
{
uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );
if( ( offset >= sizeof( xNetworkBuffers ) ) ||
( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )
return pdFALSE;
return (UBaseType_t) (pxDesc - xNetworkBuffers) + 1;
}
/*-----------------------------------------------------------*/
#else
static UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc)
{
( void ) pxDesc;
return ( UBaseType_t ) pdTRUE;
}
/*-----------------------------------------------------------*/
static void prvShowWarnings( void )
{
}
/*-----------------------------------------------------------*/
#endif /* ipconfigTCP_IP_SANITY */
BaseType_t xNetworkBuffersInitialise( void )
{
BaseType_t xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
/* In case alternative locking is used, the mutexes can be initialised
here */
ipconfigBUFFER_ALLOC_INIT();
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore );
if( xNetworkBufferSemaphore != NULL )
{
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. The buffer storage comes
from the network interface, and different hardware has different
requirements. */
vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );
for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );
}
uxMinimumFreeNetworkBuffers = ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
BaseType_t xInvalid = pdFALSE;
UBaseType_t uxCount;
/* The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
if( xNetworkBufferSemaphore != NULL )
{
/* If there is a semaphore available, there is a network buffer
available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as they are accessed from tasks and
interrupts. */
ipconfigBUFFER_ALLOC_LOCK();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&
listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )
{
uxListRemove( &( pxReturn->xBufferListItem ) );
}
else
{
xInvalid = pdTRUE;
}
}
ipconfigBUFFER_ALLOC_UNLOCK();
if( xInvalid == pdTRUE )
{
/* _RB_ Can printf() be called from an interrupt? (comment
above says this can be called from an interrupt too) */
/* _HT_ The function shall not be called from an ISR. Comment
was indeed misleading. Hopefully clear now?
So the printf()is OK here. */
FreeRTOS_debug_printf( ( "pxGetNetworkBufferWithDescriptor: INVALID BUFFER: %p (valid %lu)\n",
pxReturn, bIsValidNetworkDescriptor( pxReturn ) ) );
pxReturn = NULL;
}
else
{
/* Reading UBaseType_t, no critical section needed. */
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
/* For stats, latch the lowest number of network buffers since
booting. */
if( uxMinimumFreeNetworkBuffers > uxCount )
{
uxMinimumFreeNetworkBuffers = uxCount;
}
pxReturn->xDataLength = xRequestedSizeBytes;
#if( ipconfigTCP_IP_SANITY != 0 )
{
prvShowWarnings();
}
#endif /* ipconfigTCP_IP_SANITY */
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
/* make sure the buffer is not linked */
pxReturn->pxNextBuffer = NULL;
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
}
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
else
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
/* The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
/* If there is a semaphore available then there is a buffer available, but,
as this is called from an interrupt, only take a buffer if there are at
least baINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining. This prevents,
to a certain degree at least, a rapidly executing interrupt exhausting
buffer and in so doing preventing tasks from continuing. */
if( uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) xNetworkBufferSemaphore ) > ( UBaseType_t ) baINTERRUPT_BUFFER_GET_THRESHOLD )
{
if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
}
return pxReturn;
}
/*-----------------------------------------------------------*/
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
return xHigherPriorityTaskWoken;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xListItemAlreadyInFreeList;
if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )
{
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );
return ;
}
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
ipconfigBUFFER_ALLOC_LOCK();
{
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
}
}
ipconfigBUFFER_ALLOC_UNLOCK();
if( xListItemAlreadyInFreeList )
{
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
}
if( xListItemAlreadyInFreeList == pdFALSE )
{
xSemaphoreGive( xNetworkBufferSemaphore );
prvShowWarnings();
}
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
{
return uxMinimumFreeNetworkBuffers;
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
{
/* In BufferAllocation_1.c all network buffer are allocated with a
maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the
network buffer. */
( void ) xNewSizeBytes;
return pxNetworkBuffer;
}
/*#endif */ /* ipconfigINCLUDE_TEST_CODE */
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
*
******************************************************************************/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
/* For an Ethernet interrupt to be able to obtain a network buffer there must
be at least this number of buffers available. */
#define baINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
/* A list of free (available) NetworkBufferDescriptor_t structures. */
static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */
static UBaseType_t uxMinimumFreeNetworkBuffers = 0u;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist
in this array. The array is not accessed directly except during initialisation,
when the xFreeBuffersList is filled (as all the buffers are free when the system
is booted). */
static NetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
/* This constant is defined as true to let FreeRTOS_TCP_IP.c know that the
network buffers have constant size, large enough to hold the biggest Ethernet
packet. No resizing will be done. */
const BaseType_t xBufferAllocFixedSize = pdTRUE;
/* The semaphore used to obtain network buffers. */
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
#if( ipconfigTCP_IP_SANITY != 0 )
static char cIsLow = pdFALSE;
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
#else
static UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc );
#endif /* ipconfigTCP_IP_SANITY */
static void prvShowWarnings( void );
/* The user can define their own ipconfigBUFFER_ALLOC_LOCK() and
ipconfigBUFFER_ALLOC_UNLOCK() macros, especially for use form an ISR. If these
are not defined then default them to call the normal enter/exit critical
section macros. */
#if !defined( ipconfigBUFFER_ALLOC_LOCK )
#define ipconfigBUFFER_ALLOC_INIT( ) do {} while (0)
#define ipconfigBUFFER_ALLOC_LOCK_FROM_ISR() \
UBaseType_t uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \
{
#define ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR() \
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \
}
#define ipconfigBUFFER_ALLOC_LOCK() taskENTER_CRITICAL()
#define ipconfigBUFFER_ALLOC_UNLOCK() taskEXIT_CRITICAL()
#endif /* ipconfigBUFFER_ALLOC_LOCK */
/*-----------------------------------------------------------*/
#if( ipconfigTCP_IP_SANITY != 0 )
/* HT: SANITY code will be removed as soon as the library is stable
* and and ready to become public
* Function below gives information about the use of buffers */
#define WARN_LOW ( 2 )
#define WARN_HIGH ( ( 5 * ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) / 10 )
#endif /* ipconfigTCP_IP_SANITY */
/*-----------------------------------------------------------*/
#if( ipconfigTCP_IP_SANITY != 0 )
BaseType_t prvIsFreeBuffer( const NetworkBufferDescriptor_t *pxDescr )
{
return ( bIsValidNetworkDescriptor( pxDescr ) != 0 ) &&
( listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxDescr->xBufferListItem ) ) != 0 );
}
/*-----------------------------------------------------------*/
static void prvShowWarnings( void )
{
UBaseType_t uxCount = uxGetNumberOfFreeNetworkBuffers( );
if( ( ( cIsLow == 0 ) && ( uxCount <= WARN_LOW ) ) || ( ( cIsLow != 0 ) && ( uxCount >= WARN_HIGH ) ) )
{
cIsLow = !cIsLow;
FreeRTOS_debug_printf( ( "*** Warning *** %s %lu buffers left\n", cIsLow ? "only" : "now", uxCount ) );
}
}
/*-----------------------------------------------------------*/
UBaseType_t bIsValidNetworkDescriptor( const NetworkBufferDescriptor_t * pxDesc )
{
uint32_t offset = ( uint32_t ) ( ((const char *)pxDesc) - ((const char *)xNetworkBuffers) );
if( ( offset >= sizeof( xNetworkBuffers ) ) ||
( ( offset % sizeof( xNetworkBuffers[0] ) ) != 0 ) )
return pdFALSE;
return (UBaseType_t) (pxDesc - xNetworkBuffers) + 1;
}
/*-----------------------------------------------------------*/
#else
static UBaseType_t bIsValidNetworkDescriptor (const NetworkBufferDescriptor_t * pxDesc)
{
( void ) pxDesc;
return ( UBaseType_t ) pdTRUE;
}
/*-----------------------------------------------------------*/
static void prvShowWarnings( void )
{
}
/*-----------------------------------------------------------*/
#endif /* ipconfigTCP_IP_SANITY */
BaseType_t xNetworkBuffersInitialise( void )
{
BaseType_t xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
/* In case alternative locking is used, the mutexes can be initialised
here */
ipconfigBUFFER_ALLOC_INIT();
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore );
if( xNetworkBufferSemaphore != NULL )
{
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. The buffer storage comes
from the network interface, and different hardware has different
requirements. */
vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );
for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );
}
uxMinimumFreeNetworkBuffers = ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
BaseType_t xInvalid = pdFALSE;
UBaseType_t uxCount;
/* The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
if( xNetworkBufferSemaphore != NULL )
{
/* If there is a semaphore available, there is a network buffer
available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as they are accessed from tasks and
interrupts. */
ipconfigBUFFER_ALLOC_LOCK();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
if( ( bIsValidNetworkDescriptor( pxReturn ) != pdFALSE_UNSIGNED ) &&
listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxReturn->xBufferListItem ) ) )
{
uxListRemove( &( pxReturn->xBufferListItem ) );
}
else
{
xInvalid = pdTRUE;
}
}
ipconfigBUFFER_ALLOC_UNLOCK();
if( xInvalid == pdTRUE )
{
/* _RB_ Can printf() be called from an interrupt? (comment
above says this can be called from an interrupt too) */
/* _HT_ The function shall not be called from an ISR. Comment
was indeed misleading. Hopefully clear now?
So the printf()is OK here. */
FreeRTOS_debug_printf( ( "pxGetNetworkBufferWithDescriptor: INVALID BUFFER: %p (valid %lu)\n",
pxReturn, bIsValidNetworkDescriptor( pxReturn ) ) );
pxReturn = NULL;
}
else
{
/* Reading UBaseType_t, no critical section needed. */
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
/* For stats, latch the lowest number of network buffers since
booting. */
if( uxMinimumFreeNetworkBuffers > uxCount )
{
uxMinimumFreeNetworkBuffers = uxCount;
}
pxReturn->xDataLength = xRequestedSizeBytes;
#if( ipconfigTCP_IP_SANITY != 0 )
{
prvShowWarnings();
}
#endif /* ipconfigTCP_IP_SANITY */
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
/* make sure the buffer is not linked */
pxReturn->pxNextBuffer = NULL;
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
}
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
else
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
/* The current implementation only has a single size memory block, so
the requested size parameter is not used (yet). */
( void ) xRequestedSizeBytes;
/* If there is a semaphore available then there is a buffer available, but,
as this is called from an interrupt, only take a buffer if there are at
least baINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining. This prevents,
to a certain degree at least, a rapidly executing interrupt exhausting
buffer and in so doing preventing tasks from continuing. */
if( uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) xNetworkBufferSemaphore ) > ( UBaseType_t ) baINTERRUPT_BUFFER_GET_THRESHOLD )
{
if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
}
return pxReturn;
}
/*-----------------------------------------------------------*/
BaseType_t vNetworkBufferReleaseFromISR( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
ipconfigBUFFER_ALLOC_LOCK_FROM_ISR();
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
ipconfigBUFFER_ALLOC_UNLOCK_FROM_ISR();
xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
return xHigherPriorityTaskWoken;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xListItemAlreadyInFreeList;
if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED )
{
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) );
return ;
}
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. */
ipconfigBUFFER_ALLOC_LOCK();
{
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
}
}
ipconfigBUFFER_ALLOC_UNLOCK();
if( xListItemAlreadyInFreeList )
{
FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n",
pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) );
}
if( xListItemAlreadyInFreeList == pdFALSE )
{
xSemaphoreGive( xNetworkBufferSemaphore );
prvShowWarnings();
}
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
{
return uxMinimumFreeNetworkBuffers;
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
{
/* In BufferAllocation_1.c all network buffer are allocated with a
maximum size of 'ipTOTAL_ETHERNET_FRAME_SIZE'.No need to resize the
network buffer. */
( void ) xNewSizeBytes;
return pxNetworkBuffer;
}
/*#endif */ /* ipconfigINCLUDE_TEST_CODE */

View file

@ -1,393 +1,393 @@
/*
* FreeRTOS+TCP V2.0.11
* Copyright (C) 2017 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
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
*
******************************************************************************/
/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used,
heap_4 can be used. */
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
/* The obtained network buffer must be large enough to hold a packet that might
replace the packet that was requested to be sent. */
#if ipconfigUSE_TCP == 1
#define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t )
#else
#define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )
#endif /* ipconfigUSE_TCP == 1 */
/*_RB_ This is too complex not to have an explanation. */
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#define STATIC_ASSERT(e) \
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
#endif
/* A list of free (available) NetworkBufferDescriptor_t structures. */
static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */
static size_t uxMinimumFreeNetworkBuffers;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist
in this array. The array is not accessed directly except during initialisation,
when the xFreeBuffersList is filled (as all the buffers are free when the system
is booted). */
static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
network buffers have a variable size: resizing may be necessary */
const BaseType_t xBufferAllocFixedSize = pdFALSE;
/* The semaphore used to obtain network buffers. */
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkBuffersInitialise( void )
{
BaseType_t xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore );
if( xNetworkBufferSemaphore != NULL )
{
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
}
#endif /* configQUEUE_REGISTRY_SIZE */
/* If the trace recorder code is included name the semaphore for viewing
in FreeRTOS+Trace. */
#if( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
{
extern QueueHandle_t xNetworkEventQueue;
vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
}
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. No storage is allocated to
the buffers yet. */
for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
}
uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes )
{
uint8_t *pucEthernetBuffer;
size_t xSize = *pxRequestedSizeBytes;
if( xSize < baMINIMAL_BUFFER_SIZE )
{
/* Buffers must be at least large enough to hold a TCP-packet with
headers, or an ARP packet, in case TCP is not included. */
xSize = baMINIMAL_BUFFER_SIZE;
}
/* Round up xSize to the nearest multiple of N bytes,
where N equals 'sizeof( size_t )'. */
if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
{
xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
}
*pxRequestedSizeBytes = xSize;
/* Allocate a buffer large enough to store the requested Ethernet frame size
and a pointer to a network buffer structure (hence the addition of
ipBUFFER_PADDING bytes). */
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
configASSERT( pucEthernetBuffer );
if( pucEthernetBuffer != NULL )
{
/* Enough space is left at the start of the buffer to place a pointer to
the network buffer structure that references this Ethernet buffer.
Return a pointer to the start of the Ethernet buffer itself. */
pucEthernetBuffer += ipBUFFER_PADDING;
}
return pucEthernetBuffer;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer )
{
/* There is space before the Ethernet buffer in which a pointer to the
network buffer that references this Ethernet buffer is stored. Remove the
space before freeing the buffer. */
if( pucEthernetBuffer != NULL )
{
pucEthernetBuffer -= ipBUFFER_PADDING;
vPortFree( ( void * ) pucEthernetBuffer );
}
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
size_t uxCount;
if( xNetworkBufferSemaphore != NULL )
{
if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
{
/* ARP packets can replace application packets, so the storage must be
at least large enough to hold an ARP. */
xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
}
/* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes
to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
xRequestedSizeBytes += 2u;
if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
{
xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
}
/* If there is a semaphore available, there is a network buffer available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
taskENTER_CRITICAL();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
taskEXIT_CRITICAL();
/* Reading UBaseType_t, no critical section needed. */
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
if( uxMinimumFreeNetworkBuffers > uxCount )
{
uxMinimumFreeNetworkBuffers = uxCount;
}
/* Allocate storage of exactly the requested size to the buffer. */
configASSERT( pxReturn->pucEthernetBuffer == NULL );
if( xRequestedSizeBytes > 0 )
{
/* Extra space is obtained so a pointer to the network buffer can
be stored at the beginning of the buffer. */
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
if( pxReturn->pucEthernetBuffer == NULL )
{
/* The attempt to allocate storage for the buffer payload failed,
so the network buffer structure cannot be used and must be
released. */
vReleaseNetworkBufferAndDescriptor( pxReturn );
pxReturn = NULL;
}
else
{
/* Store a pointer to the network buffer structure in the
buffer storage area, then move the buffer pointer on past the
stored pointer so the pointer value is not overwritten by the
application when the buffer is used. */
*( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
/* Store the actual size of the allocated buffer, which may be
greater than the original requested size. */
pxReturn->xDataLength = xRequestedSizeBytes;
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
/* make sure the buffer is not linked */
pxReturn->pxNextBuffer = NULL;
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
}
}
else
{
/* A descriptor is being returned without an associated buffer being
allocated. */
}
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
else
{
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
return pxReturn;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xListItemAlreadyInFreeList;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. Release the
storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED
IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
MEMORY. For example, heap_2 must not be used, heap_4 can be used. */
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = NULL;
taskENTER_CRITICAL();
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
}
taskEXIT_CRITICAL();
/*
* Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
* The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
*/
if( xListItemAlreadyInFreeList == pdFALSE )
{
if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
{
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
else
{
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
/*-----------------------------------------------------------*/
/*
* Returns the number of free network buffers
*/
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
{
return uxMinimumFreeNetworkBuffers;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
{
size_t xOriginalLength;
uint8_t *pucBuffer;
xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
if( pucBuffer == NULL )
{
/* In case the allocation fails, return NULL. */
pxNetworkBuffer = NULL;
}
else
{
pxNetworkBuffer->xDataLength = xNewSizeBytes;
if( xNewSizeBytes > xOriginalLength )
{
xNewSizeBytes = xOriginalLength;
}
memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
}
return pxNetworkBuffer;
}
/*
* FreeRTOS+TCP V2.0.11
* Copyright (C) 2017 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
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/******************************************************************************
*
* See the following web page for essential buffer allocation scheme usage and
* configuration details:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
*
******************************************************************************/
/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used,
heap_4 can be used. */
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
/* The obtained network buffer must be large enough to hold a packet that might
replace the packet that was requested to be sent. */
#if ipconfigUSE_TCP == 1
#define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t )
#else
#define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t )
#endif /* ipconfigUSE_TCP == 1 */
/*_RB_ This is too complex not to have an explanation. */
#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#define STATIC_ASSERT(e) \
;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) }
STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
#endif
/* A list of free (available) NetworkBufferDescriptor_t structures. */
static List_t xFreeBuffersList;
/* Some statistics about the use of buffers. */
static size_t uxMinimumFreeNetworkBuffers;
/* Declares the pool of NetworkBufferDescriptor_t structures that are available
to the system. All the network buffers referenced from xFreeBuffersList exist
in this array. The array is not accessed directly except during initialisation,
when the xFreeBuffersList is filled (as all the buffers are free when the system
is booted). */
static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
network buffers have a variable size: resizing may be necessary */
const BaseType_t xBufferAllocFixedSize = pdFALSE;
/* The semaphore used to obtain network buffers. */
static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkBuffersInitialise( void )
{
BaseType_t xReturn, x;
/* Only initialise the buffers and their associated kernel objects if they
have not been initialised before. */
if( xNetworkBufferSemaphore == NULL )
{
xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
configASSERT( xNetworkBufferSemaphore );
if( xNetworkBufferSemaphore != NULL )
{
#if ( configQUEUE_REGISTRY_SIZE > 0 )
{
vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
}
#endif /* configQUEUE_REGISTRY_SIZE */
/* If the trace recorder code is included name the semaphore for viewing
in FreeRTOS+Trace. */
#if( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
{
extern QueueHandle_t xNetworkEventQueue;
vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
}
#endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
vListInitialise( &xFreeBuffersList );
/* Initialise all the network buffers. No storage is allocated to
the buffers yet. */
for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
/* Initialise and set the owner of the buffer list items. */
xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
/* Currently, all buffers are available for use. */
vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
}
uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
}
}
if( xNetworkBufferSemaphore == NULL )
{
xReturn = pdFAIL;
}
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
uint8_t *pucGetNetworkBuffer( size_t *pxRequestedSizeBytes )
{
uint8_t *pucEthernetBuffer;
size_t xSize = *pxRequestedSizeBytes;
if( xSize < baMINIMAL_BUFFER_SIZE )
{
/* Buffers must be at least large enough to hold a TCP-packet with
headers, or an ARP packet, in case TCP is not included. */
xSize = baMINIMAL_BUFFER_SIZE;
}
/* Round up xSize to the nearest multiple of N bytes,
where N equals 'sizeof( size_t )'. */
if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
{
xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
}
*pxRequestedSizeBytes = xSize;
/* Allocate a buffer large enough to store the requested Ethernet frame size
and a pointer to a network buffer structure (hence the addition of
ipBUFFER_PADDING bytes). */
pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
configASSERT( pucEthernetBuffer );
if( pucEthernetBuffer != NULL )
{
/* Enough space is left at the start of the buffer to place a pointer to
the network buffer structure that references this Ethernet buffer.
Return a pointer to the start of the Ethernet buffer itself. */
pucEthernetBuffer += ipBUFFER_PADDING;
}
return pucEthernetBuffer;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBuffer( uint8_t *pucEthernetBuffer )
{
/* There is space before the Ethernet buffer in which a pointer to the
network buffer that references this Ethernet buffer is stored. Remove the
space before freeing the buffer. */
if( pucEthernetBuffer != NULL )
{
pucEthernetBuffer -= ipBUFFER_PADDING;
vPortFree( ( void * ) pucEthernetBuffer );
}
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
{
NetworkBufferDescriptor_t *pxReturn = NULL;
size_t uxCount;
if( xNetworkBufferSemaphore != NULL )
{
if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
{
/* ARP packets can replace application packets, so the storage must be
at least large enough to hold an ARP. */
xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
}
/* Add 2 bytes to xRequestedSizeBytes and round up xRequestedSizeBytes
to the nearest multiple of N bytes, where N equals 'sizeof( size_t )'. */
xRequestedSizeBytes += 2u;
if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
{
xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
}
/* If there is a semaphore available, there is a network buffer available. */
if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
{
/* Protect the structure as it is accessed from tasks and interrupts. */
taskENTER_CRITICAL();
{
pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
uxListRemove( &( pxReturn->xBufferListItem ) );
}
taskEXIT_CRITICAL();
/* Reading UBaseType_t, no critical section needed. */
uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
if( uxMinimumFreeNetworkBuffers > uxCount )
{
uxMinimumFreeNetworkBuffers = uxCount;
}
/* Allocate storage of exactly the requested size to the buffer. */
configASSERT( pxReturn->pucEthernetBuffer == NULL );
if( xRequestedSizeBytes > 0 )
{
/* Extra space is obtained so a pointer to the network buffer can
be stored at the beginning of the buffer. */
pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
if( pxReturn->pucEthernetBuffer == NULL )
{
/* The attempt to allocate storage for the buffer payload failed,
so the network buffer structure cannot be used and must be
released. */
vReleaseNetworkBufferAndDescriptor( pxReturn );
pxReturn = NULL;
}
else
{
/* Store a pointer to the network buffer structure in the
buffer storage area, then move the buffer pointer on past the
stored pointer so the pointer value is not overwritten by the
application when the buffer is used. */
*( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
/* Store the actual size of the allocated buffer, which may be
greater than the original requested size. */
pxReturn->xDataLength = xRequestedSizeBytes;
#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
/* make sure the buffer is not linked */
pxReturn->pxNextBuffer = NULL;
}
#endif /* ipconfigUSE_LINKED_RX_MESSAGES */
}
}
else
{
/* A descriptor is being returned without an associated buffer being
allocated. */
}
}
}
if( pxReturn == NULL )
{
iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
}
else
{
iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
}
return pxReturn;
}
/*-----------------------------------------------------------*/
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xListItemAlreadyInFreeList;
/* Ensure the buffer is returned to the list of free buffers before the
counting semaphore is 'given' to say a buffer is available. Release the
storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED
IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
MEMORY. For example, heap_2 must not be used, heap_4 can be used. */
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = NULL;
taskENTER_CRITICAL();
{
xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
if( xListItemAlreadyInFreeList == pdFALSE )
{
vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
}
}
taskEXIT_CRITICAL();
/*
* Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
* The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
*/
if( xListItemAlreadyInFreeList == pdFALSE )
{
if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
{
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
else
{
iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
}
}
/*-----------------------------------------------------------*/
/*
* Returns the number of free network buffers
*/
UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
{
return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
}
/*-----------------------------------------------------------*/
UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
{
return uxMinimumFreeNetworkBuffers;
}
/*-----------------------------------------------------------*/
NetworkBufferDescriptor_t *pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, size_t xNewSizeBytes )
{
size_t xOriginalLength;
uint8_t *pucBuffer;
xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
if( pucBuffer == NULL )
{
/* In case the allocation fails, return NULL. */
pxNetworkBuffer = NULL;
}
else
{
pxNetworkBuffer->xDataLength = xNewSizeBytes;
if( xNewSizeBytes > xOriginalLength )
{
xNewSizeBytes = xOriginalLength;
}
memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
}
return pxNetworkBuffer;
}

View file

@ -0,0 +1,3 @@
Update pack_struct_start.h and pack_struct_end.h for your architecure.
These files define the specifiers needed by your compiler to properly pack struct data
need by FreeRTOS+TCP.

View file

@ -0,0 +1,32 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
; /* FIX ME. Update for the compiler specifier needed at end of a struct declartion to pack the struct. */

View file

@ -0,0 +1,32 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
/* FIX ME. Update for the compiler specifier needed at the start of a struct declartion to pack the struct. */

View file

@ -1,46 +1,46 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
__attribute__( (packed) );
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
__attribute__( (packed) );

View file

@ -1,48 +1,48 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
/* Nothing to do here. */
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
/* Nothing to do here. */

View file

@ -1,47 +1,47 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;

View file

@ -1,49 +1,49 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
__packed
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
__packed

View file

@ -1,33 +1,33 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;
#pragma pack(pop)
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;
#pragma pack(pop)

View file

@ -1,48 +1,48 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#pragma pack(push,1)
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#pragma pack(push,1)

View file

@ -1,48 +1,48 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;
#pragma pack( pop )
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
;
#pragma pack( pop )

View file

@ -1,47 +1,47 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#pragma pack( push, 1 )
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#pragma pack( push, 1 )

View file

@ -1,60 +1,60 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
;
#pragma unpack
#endif
#endif
#ifdef __RX
#ifdef __CCRX__
;
#pragma packoption
#endif
#endif
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
;
#pragma unpack
#endif
#endif
#ifdef __RX
#ifdef __CCRX__
;
#pragma packoption
#endif
#endif

View file

@ -1,58 +1,58 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
#pragma pack 1
#endif
#endif
#ifdef __RX
#ifdef __CCRX__
#pragma pack
#endif
#endif
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/*****************************************************************************
*
* See the following URL for an explanation of this file:
* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Compiler_Porting.html
*
*****************************************************************************/
#ifdef _SH
#ifdef __RENESAS__
#pragma pack 1
#endif
#endif
#ifdef __RX
#ifdef __CCRX__
#pragma pack
#endif
#endif

View file

@ -1,454 +1,454 @@
/**
* \file
*
* \brief API driver for KSZ8051MNL PHY component.
*
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "FreeRTOSIPConfig.h"
#include "ethernet_phy.h"
#include "instance/gmac.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
*
* Driver for the ksz8051mnl component. This driver provides access to the main
* features of the PHY.
*
* \section dependencies Dependencies
* This driver depends on the following modules:
* - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
*
* @{
*/
SPhyProps phyProps;
/* Max PHY number */
#define ETH_PHY_MAX_ADDR 31
/* Ethernet PHY operation max retry count */
#define ETH_PHY_RETRY_MAX 1000000
/* Ethernet PHY operation timeout */
#define ETH_PHY_TIMEOUT 10
/**
* \brief Find a valid PHY Address ( from addrStart to 31 ).
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_start_addr Start address of the PHY to be searched.
*
* \return 0xFF when no valid PHY address is found.
*/
int ethernet_phy_addr = 0;
static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_start_addr)
{
uint32_t ul_value = 0;
uint8_t uc_cnt;
uint8_t uc_phy_address = uc_phy_addr;
gmac_enable_management(p_gmac, true);
/*
#define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05
PHYID1 = 0x0022
PHYID2 = 0x1550
0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
*/
/* Check the current PHY address */
gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
/* Find another one */
if (ul_value != GMII_OUI_MSB) {
ethernet_phy_addr = 0xFF;
for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
uc_phy_address = (uc_phy_address + 1) & 0x1F;
ul_value = 0;
gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
if (ul_value == GMII_OUI_MSB) {
ethernet_phy_addr = uc_phy_address;
break;
}
}
}
gmac_enable_management(p_gmac, false);
if (ethernet_phy_addr != 0xFF) {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
}
return ethernet_phy_addr;
}
/**
* \brief Perform a HW initialization to the PHY and set up clocks.
*
* This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
{
uint8_t uc_rc = GMAC_TIMEOUT;
uint8_t uc_phy;
ethernet_phy_reset(GMAC,uc_phy_addr);
/* Configure GMAC runtime clock */
uc_rc = gmac_set_mdc_clock(p_gmac, mck);
if (uc_rc != GMAC_OK) {
return 0;
}
/* Check PHY Address */
uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
if (uc_phy == 0xFF) {
return 0;
}
if (uc_phy != uc_phy_addr) {
ethernet_phy_reset(p_gmac, uc_phy_addr);
}
phy_props.phy_chn = uc_phy;
return uc_phy;
}
/**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag)
{
uint32_t ul_stat1;
uint32_t ul_stat2;
uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
uc_phy_address = uc_phy_addr;
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return GMAC_INVALID;
}
if (uc_apply_setting_flag == 0) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
/* Read advertisement */
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
phy_props.phy_stat1 = ul_stat1;
phy_props.phy_stat2 = ul_stat2;
if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
/* Set GMAC for 100BaseTX and Full Duplex */
uc_speed = true;
uc_fd = true;
} else
if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
/* Set MII for 100BaseTX and Half Duplex */
uc_speed = true;
uc_fd = false;
} else
if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
/* Set MII for 10BaseT and Full Duplex */
uc_speed = false;
uc_fd = true;
} else
if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
/* Set MII for 10BaseT and Half Duplex */
uc_speed = false;
uc_fd = false;
}
gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd);
/* Start the GMAC transfers */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
PhyProps_t phy_props;
/**
* \brief Issue an auto negotiation of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
{
uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
uint32_t ul_value;
uint32_t ul_phy_anar;
uint32_t ul_retry_count = 0;
uint8_t uc_speed = 0;
uint8_t uc_fd=0;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
/* Set up control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -1;
return uc_rc;
}
ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -2;
return uc_rc;
}
/*
* Set the Auto_negotiation Advertisement Register.
* MII advertising for Next page.
* 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
*/
ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
GMII_AN_IEEE_802_3;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -3;
return uc_rc;
}
/* Read & modify control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -4;
return uc_rc;
}
ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -5;
return uc_rc;
}
/* Restart auto negotiation */
ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
ul_value &= ~(uint32_t)GMII_ISOLATE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -6;
return uc_rc;
}
/* Check if auto negotiation is completed */
while (1) {
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -7;
return uc_rc;
}
/* Done successfully */
if (ul_value & GMII_AUTONEG_COMP) {
break;
}
/* Timeout check */
if (ul_retry_max) {
if (++ul_retry_count >= ul_retry_max) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -8;
return GMAC_TIMEOUT;
}
}
}
/* Get the auto negotiate link partner base page */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -9;
return uc_rc;
}
/* Set up the GMAC link speed */
if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
/* Set MII for 100BaseTX and Full Duplex */
uc_speed = true;
uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
/* Set MII for 10BaseT and Full Duplex */
uc_speed = false;
uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
/* Set MII for 100BaseTX and half Duplex */
uc_speed = true;
uc_fd = false;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
/* Set MII for 10BaseT and half Duplex */
uc_speed = false;
uc_fd = false;
}
gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd);
/* Select Media Independent Interface type */
gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
gmac_enable_transmit(GMAC, true);
gmac_enable_receive(GMAC, true);
gmac_enable_management(p_gmac, false);
phy_props.phy_result = 1;
return uc_rc;
}
/**
* \brief Issue a SW reset to reset all registers of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
{
uint32_t ul_bmcr = GMII_RESET;
uint8_t uc_phy_address = uc_phy_addr;
uint32_t ul_timeout = ETH_PHY_TIMEOUT;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
ul_bmcr = GMII_RESET;
gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
do {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
ul_timeout--;
} while ((ul_bmcr & GMII_RESET) && ul_timeout);
gmac_enable_management(p_gmac, false);
if (!ul_timeout) {
uc_rc = GMAC_OK;
}
return (uc_rc);
}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
/**
* \}
*/
/**
* \file
*
* \brief API driver for KSZ8051MNL PHY component.
*
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "FreeRTOSIPConfig.h"
#include "ethernet_phy.h"
#include "instance/gmac.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup ksz8051mnl_ethernet_phy_group PHY component (KSZ8051MNL)
*
* Driver for the ksz8051mnl component. This driver provides access to the main
* features of the PHY.
*
* \section dependencies Dependencies
* This driver depends on the following modules:
* - \ref gmac_group Ethernet Media Access Controller (GMAC) module.
*
* @{
*/
SPhyProps phyProps;
/* Max PHY number */
#define ETH_PHY_MAX_ADDR 31
/* Ethernet PHY operation max retry count */
#define ETH_PHY_RETRY_MAX 1000000
/* Ethernet PHY operation timeout */
#define ETH_PHY_TIMEOUT 10
/**
* \brief Find a valid PHY Address ( from addrStart to 31 ).
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_start_addr Start address of the PHY to be searched.
*
* \return 0xFF when no valid PHY address is found.
*/
int ethernet_phy_addr = 0;
static uint8_t ethernet_phy_find_valid(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_start_addr)
{
uint32_t ul_value = 0;
uint8_t uc_cnt;
uint8_t uc_phy_address = uc_phy_addr;
gmac_enable_management(p_gmac, true);
/*
#define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05
PHYID1 = 0x0022
PHYID2 = 0x1550
0001_0101_0101_0000 = 0x1550 <= mask should be 0xFFF0
*/
/* Check the current PHY address */
gmac_phy_read(p_gmac, uc_phy_addr, GMII_PHYID1, &ul_value);
/* Find another one */
if (ul_value != GMII_OUI_MSB) {
ethernet_phy_addr = 0xFF;
for (uc_cnt = uc_start_addr; uc_cnt <= ETH_PHY_MAX_ADDR; uc_cnt++) {
uc_phy_address = (uc_phy_address + 1) & 0x1F;
ul_value = 0;
gmac_phy_read(p_gmac, uc_phy_address, GMII_PHYID1, &ul_value);
if (ul_value == GMII_OUI_MSB) {
ethernet_phy_addr = uc_phy_address;
break;
}
}
}
gmac_enable_management(p_gmac, false);
if (ethernet_phy_addr != 0xFF) {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_value);
}
return ethernet_phy_addr;
}
/**
* \brief Perform a HW initialization to the PHY and set up clocks.
*
* This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the emacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t mck)
{
uint8_t uc_rc = GMAC_TIMEOUT;
uint8_t uc_phy;
ethernet_phy_reset(GMAC,uc_phy_addr);
/* Configure GMAC runtime clock */
uc_rc = gmac_set_mdc_clock(p_gmac, mck);
if (uc_rc != GMAC_OK) {
return 0;
}
/* Check PHY Address */
uc_phy = ethernet_phy_find_valid(p_gmac, uc_phy_addr, 0);
if (uc_phy == 0xFF) {
return 0;
}
if (uc_phy != uc_phy_addr) {
ethernet_phy_reset(p_gmac, uc_phy_addr);
}
phy_props.phy_chn = uc_phy;
return uc_phy;
}
/**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag)
{
uint32_t ul_stat1;
uint32_t ul_stat2;
uint8_t uc_phy_address, uc_speed = true, uc_fd = true;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
uc_phy_address = uc_phy_addr;
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_BMSR, &ul_stat1);
if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
if ((ul_stat1 & GMII_LINK_STATUS) == 0) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return GMAC_INVALID;
}
if (uc_apply_setting_flag == 0) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
/* Read advertisement */
uc_rc = gmac_phy_read(p_gmac, uc_phy_address, GMII_ANAR, &ul_stat2);
phy_props.phy_stat1 = ul_stat1;
phy_props.phy_stat2 = ul_stat2;
if (uc_rc != GMAC_OK) {
/* Disable PHY management and start the GMAC transfer */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
if ((ul_stat1 & GMII_100BASE_TX_FD) && (ul_stat2 & GMII_100TX_FDX)) {
/* Set GMAC for 100BaseTX and Full Duplex */
uc_speed = true;
uc_fd = true;
} else
if ((ul_stat1 & GMII_100BASE_T4_HD) && (ul_stat2 & GMII_100TX_HDX)) {
/* Set MII for 100BaseTX and Half Duplex */
uc_speed = true;
uc_fd = false;
} else
if ((ul_stat1 & GMII_10BASE_T_FD) && (ul_stat2 & GMII_10_FDX)) {
/* Set MII for 10BaseT and Full Duplex */
uc_speed = false;
uc_fd = true;
} else
if ((ul_stat1 & GMII_10BASE_T_HD) && (ul_stat2 & GMII_10_HDX)) {
/* Set MII for 10BaseT and Half Duplex */
uc_speed = false;
uc_fd = false;
}
gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd);
/* Start the GMAC transfers */
gmac_enable_management(p_gmac, false);
return uc_rc;
}
PhyProps_t phy_props;
/**
* \brief Issue an auto negotiation of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr)
{
uint32_t ul_retry_max = ETH_PHY_RETRY_MAX;
uint32_t ul_value;
uint32_t ul_phy_anar;
uint32_t ul_retry_count = 0;
uint8_t uc_speed = 0;
uint8_t uc_fd=0;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
/* Set up control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -1;
return uc_rc;
}
ul_value &= ~(uint32_t)GMII_AUTONEG; /* Remove auto-negotiation enable */
ul_value &= ~(uint32_t)(GMII_LOOPBACK | GMII_POWER_DOWN);
ul_value |= (uint32_t)GMII_ISOLATE; /* Electrically isolate PHY */
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -2;
return uc_rc;
}
/*
* Set the Auto_negotiation Advertisement Register.
* MII advertising for Next page.
* 100BaseTxFD and HD, 10BaseTFD and HD, IEEE 802.3.
*/
ul_phy_anar = GMII_100TX_FDX | GMII_100TX_HDX | GMII_10_FDX | GMII_10_HDX |
GMII_AN_IEEE_802_3;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_ANAR, ul_phy_anar);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -3;
return uc_rc;
}
/* Read & modify control register */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMCR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -4;
return uc_rc;
}
ul_value |= GMII_SPEED_SELECT | GMII_AUTONEG | GMII_DUPLEX_MODE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -5;
return uc_rc;
}
/* Restart auto negotiation */
ul_value |= (uint32_t)GMII_RESTART_AUTONEG;
ul_value &= ~(uint32_t)GMII_ISOLATE;
uc_rc = gmac_phy_write(p_gmac, uc_phy_addr, GMII_BMCR, ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -6;
return uc_rc;
}
/* Check if auto negotiation is completed */
while (1) {
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_BMSR, &ul_value);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -7;
return uc_rc;
}
/* Done successfully */
if (ul_value & GMII_AUTONEG_COMP) {
break;
}
/* Timeout check */
if (ul_retry_max) {
if (++ul_retry_count >= ul_retry_max) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -8;
return GMAC_TIMEOUT;
}
}
}
/* Get the auto negotiate link partner base page */
uc_rc = gmac_phy_read(p_gmac, uc_phy_addr, GMII_PCR1, &phy_props.phy_params);
if (uc_rc != GMAC_OK) {
gmac_enable_management(p_gmac, false);
phy_props.phy_result = -9;
return uc_rc;
}
/* Set up the GMAC link speed */
if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_FDX) {
/* Set MII for 100BaseTX and Full Duplex */
uc_speed = true;
uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_FDX) {
/* Set MII for 10BaseT and Full Duplex */
uc_speed = false;
uc_fd = true;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_100TX_HDX) {
/* Set MII for 100BaseTX and half Duplex */
uc_speed = true;
uc_fd = false;
} else if ((ul_phy_anar & phy_props.phy_params) & GMII_10_HDX) {
/* Set MII for 10BaseT and half Duplex */
uc_speed = false;
uc_fd = false;
}
gmac_set_speed(p_gmac, uc_speed);
gmac_enable_full_duplex(p_gmac, uc_fd);
/* Select Media Independent Interface type */
gmac_select_mii_mode(p_gmac, ETH_PHY_MODE);
gmac_enable_transmit(GMAC, true);
gmac_enable_receive(GMAC, true);
gmac_enable_management(p_gmac, false);
phy_props.phy_result = 1;
return uc_rc;
}
/**
* \brief Issue a SW reset to reset all registers of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr)
{
uint32_t ul_bmcr = GMII_RESET;
uint8_t uc_phy_address = uc_phy_addr;
uint32_t ul_timeout = ETH_PHY_TIMEOUT;
uint8_t uc_rc = GMAC_TIMEOUT;
gmac_enable_management(p_gmac, true);
ul_bmcr = GMII_RESET;
gmac_phy_write(p_gmac, uc_phy_address, GMII_BMCR, ul_bmcr);
do {
gmac_phy_read(p_gmac, uc_phy_address, GMII_BMCR, &ul_bmcr);
ul_timeout--;
} while ((ul_bmcr & GMII_RESET) && ul_timeout);
gmac_enable_management(p_gmac, false);
if (!ul_timeout) {
uc_rc = GMAC_OK;
}
return (uc_rc);
}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
/**
* \}
*/

View file

@ -1,281 +1,281 @@
/**
* \file
*
* \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
*
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
#ifndef ETHERNET_PHY_H_INCLUDED
#define ETHERNET_PHY_H_INCLUDED
#include "compiler.h"
#ifdef __cplusplus
extern "C" {
#endif
// IEEE defined Registers
#define GMII_BMCR 0x00 // Basic Control
#define GMII_BMSR 0x01 // Basic Status
#define GMII_PHYID1 0x02 // PHY Idendifier 1
#define GMII_PHYID2 0x03 // PHY Idendifier 2
#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement
#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability
#define GMII_ANER 0x06 // Auto-negotiation Expansion
#define GMII_ANNPR 0x07 // Auto-negotiation Next Page
#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability
//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved
//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved
#define GMII_AFECR1 0x11 // AFE Control 1
//#define GMII_ERDWR 12 // Extend Register - Data Write Register
//#define GMII_ERDRR 13 // Extend Register - Data Read Register
//14 reserved
#define GMII_RXERCR 0x15 // RXER Counter
#define PHY_REG_01_BMSR 0x01 // Basic mode status register
#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
#define PHY_REG_05_LPA 0x05 // Link partner ability reg
#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
#define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register
#define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register
#define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register
#define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED
#define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register
#define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register
#define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register
#define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register
#define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register
#define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register
#define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register
#define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register
#define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control
#define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED
#define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register
#define PHY_REG_1E_RESERVED3 0x1E //
#define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED
#define PHY_REG_1E_PHYCR_1 0x1E //
#define PHY_REG_1F_PHYCR_2 0x1F //
#define PHY_SPEED_10 1
#define PHY_SPEED_100 2
#define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)
#define PHY_MDIX_DIRECT 1
#define PHY_MDIX_CROSSED 2
#define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
#define PHY_DUPLEX_HALF 1
#define PHY_DUPLEX_FULL 2
#define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
typedef struct _SPhyProps {
unsigned char speed;
unsigned char mdix;
unsigned char duplex;
unsigned char spare;
} SPhyProps;
const char *phyPrintable (const SPhyProps *apProps);
extern SPhyProps phyProps;
#define GMII_OMSOR 0x16 // Operation Mode Strap Override
#define GMII_OMSSR 0x17 // Operation Mode Strap Status
#define GMII_ECR 0x18 // Expanded Control
//#define GMII_DPPSR 19 // Digital PMA/PCS Status
//20 reserved
//#define GMII_RXERCR 21 // RXER Counter Register
//22-26 reserved
#define GMII_ICSR 0x1B // Interrupt Control/Status
//#define GMII_DDC1R 28 // Digital Debug Control 1 Register
#define GMII_LCSR 0x1D // LinkMD Control/Status
//29-30 reserved
#define GMII_PCR1 0x1E // PHY Control 1
#define GMII_PCR2 0x1F // PHY Control 2
/*
//Extend Registers
#define GMII_CCR 256 // Common Control Register
#define GMII_SSR 257 // Strap Status Register
#define GMII_OMSOR 258 // Operation Mode Strap Override Register
#define GMII_OMSSR 259 // Operation Mode Strap Status Register
#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register
#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register
#define GMII_ATR 263 // Analog Test Register
*/
// Bit definitions: GMII_BMCR 0x00 Basic Control
#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps
#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test
//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved
// Reserved 6 to 0 // Read as 0, ignore on write
// Bit definitions: GMII_BMSR 0x01 Basic Status
#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
// Reserved 10 to79 // Read as 0, ignore on write
//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
// Reserved 7
#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
#define GMII_LINK_STATUS (1 << 2) // Link Status
#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
#define GMII_LSB_MASK 0x3F
#define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05
// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement
// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
#define GMII_NP (1 << 15) // Next page Indication
// Reserved 7
#define GMII_RF (1 << 13) // Remote Fault
// Reserved 12 // Write as 0, ignore on read
#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
// 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
#define GMII_100T4 (1 << 9) // 100BASE-T4 Support
#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support
#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
#define GMII_10_HDX (1 << 5) // 10BASE-T Support
// Selector 4 to 0 // Protocol Selection Bits
#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3
// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
// Reserved 15 to 5 // Read as 0, ignore on write
#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault
#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able
#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able
#define GMII_PAGE_RX (1 << 1) // New Page Received
#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able
/**
* \brief Perform a HW initialization to the PHY and set up clocks.
*
* This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
/**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag);
/**
* \brief Issue an auto negotiation of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
/**
* \brief Issue a SW reset to reset all registers of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
typedef struct xPHY_PROPS {
signed char phy_result;
uint32_t phy_params;
uint32_t phy_stat1;
uint32_t phy_stat2;
unsigned char phy_chn;
} PhyProps_t;
extern PhyProps_t phy_props;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */
/**
* \file
*
* \brief KSZ8051MNL (Ethernet PHY) driver for SAM.
*
* Copyright (c) 2013 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
#ifndef ETHERNET_PHY_H_INCLUDED
#define ETHERNET_PHY_H_INCLUDED
#include "compiler.h"
#ifdef __cplusplus
extern "C" {
#endif
// IEEE defined Registers
#define GMII_BMCR 0x00 // Basic Control
#define GMII_BMSR 0x01 // Basic Status
#define GMII_PHYID1 0x02 // PHY Idendifier 1
#define GMII_PHYID2 0x03 // PHY Idendifier 2
#define GMII_ANAR 0x04 // Auto_Negotiation Advertisement
#define GMII_ANLPAR 0x05 // Auto_negotiation Link Partner Ability
#define GMII_ANER 0x06 // Auto-negotiation Expansion
#define GMII_ANNPR 0x07 // Auto-negotiation Next Page
#define GMII_ANLPNPAR 0x08 // Link Partner Next Page Ability
//#define GMII_1000BTCR 9 // 1000Base-T Control // Reserved
//#define GMII_1000BTSR 10 // 1000Base-T Status // Reserved
#define GMII_AFECR1 0x11 // AFE Control 1
//#define GMII_ERDWR 12 // Extend Register - Data Write Register
//#define GMII_ERDRR 13 // Extend Register - Data Read Register
//14 reserved
#define GMII_RXERCR 0x15 // RXER Counter
#define PHY_REG_01_BMSR 0x01 // Basic mode status register
#define PHY_REG_02_PHYSID1 0x02 // PHYS ID 1
#define PHY_REG_03_PHYSID2 0x03 // PHYS ID 2
#define PHY_REG_04_ADVERTISE 0x04 // Advertisement control reg
#define PHY_REG_05_LPA 0x05 // Link partner ability reg
#define PHY_REG_06_ANER 0x06 // 6 RW Auto-Negotiation Expansion Register
#define PHY_REG_07_ANNPTR 0x07 // 7 RW Auto-Negotiation Next Page TX
#define PHY_REG_08_RESERVED0 0x08 // 0x08..0x0Fh 8-15 RW RESERVED
#define PHY_REG_10_PHYSTS 0x10 // 16 RO PHY Status Register
#define PHY_REG_11_MICR 0x11 // 17 RW MII Interrupt Control Register
#define PHY_REG_12_MISR 0x12 // 18 RO MII Interrupt Status Register
#define PHY_REG_13_RESERVED1 0x13 // 19 RW RESERVED
#define PHY_REG_14_FCSCR 0x14 // 20 RO False Carrier Sense Counter Register
#define PHY_REG_15_RECR 0x15 // 21 RO Receive Error Counter Register
#define PHY_REG_16_PCSR 0x16 // 22 RW PCS Sub-Layer Configuration and Status Register
#define PHY_REG_17_RBR 0x17 // 23 RW RMII and Bypass Register
#define PHY_REG_18_LEDCR 0x18 // 24 RW LED Direct Control Register
#define PHY_REG_19_PHYCR 0x19 // 25 RW PHY Control Register
#define PHY_REG_1A_10BTSCR 0x1A // 26 RW 10Base-T Status/Control Register
#define PHY_REG_1B_CDCTRL1 0x1B // 27 RW CD Test Control Register and BIST Extensions Register
#define PHY_REG_1B_INT_CTRL 0x1B // 27 RW KSZ8041NL interrupt control
#define PHY_REG_1C_RESERVED2 0x1C // 28 RW RESERVED
#define PHY_REG_1D_EDCR 0x1D // 29 RW Energy Detect Control Register
#define PHY_REG_1E_RESERVED3 0x1E //
#define PHY_REG_1F_RESERVED4 0x1F // 30-31 RW RESERVED
#define PHY_REG_1E_PHYCR_1 0x1E //
#define PHY_REG_1F_PHYCR_2 0x1F //
#define PHY_SPEED_10 1
#define PHY_SPEED_100 2
#define PHY_SPEED_AUTO (PHY_SPEED_10|PHY_SPEED_100)
#define PHY_MDIX_DIRECT 1
#define PHY_MDIX_CROSSED 2
#define PHY_MDIX_AUTO (PHY_MDIX_CROSSED|PHY_MDIX_DIRECT)
#define PHY_DUPLEX_HALF 1
#define PHY_DUPLEX_FULL 2
#define PHY_DUPLEX_AUTO (PHY_DUPLEX_FULL|PHY_DUPLEX_HALF)
typedef struct _SPhyProps {
unsigned char speed;
unsigned char mdix;
unsigned char duplex;
unsigned char spare;
} SPhyProps;
const char *phyPrintable (const SPhyProps *apProps);
extern SPhyProps phyProps;
#define GMII_OMSOR 0x16 // Operation Mode Strap Override
#define GMII_OMSSR 0x17 // Operation Mode Strap Status
#define GMII_ECR 0x18 // Expanded Control
//#define GMII_DPPSR 19 // Digital PMA/PCS Status
//20 reserved
//#define GMII_RXERCR 21 // RXER Counter Register
//22-26 reserved
#define GMII_ICSR 0x1B // Interrupt Control/Status
//#define GMII_DDC1R 28 // Digital Debug Control 1 Register
#define GMII_LCSR 0x1D // LinkMD Control/Status
//29-30 reserved
#define GMII_PCR1 0x1E // PHY Control 1
#define GMII_PCR2 0x1F // PHY Control 2
/*
//Extend Registers
#define GMII_CCR 256 // Common Control Register
#define GMII_SSR 257 // Strap Status Register
#define GMII_OMSOR 258 // Operation Mode Strap Override Register
#define GMII_OMSSR 259 // Operation Mode Strap Status Register
#define GMII_RCCPSR 260 // RGMII Clock and Control Pad Skew Register
#define GMII_RRDPSR 261 // RGMII RX Data Pad Skew Register
#define GMII_ATR 263 // Analog Test Register
*/
// Bit definitions: GMII_BMCR 0x00 Basic Control
#define GMII_RESET (1 << 15) // 1= Software Reset; 0=Normal Operation
#define GMII_LOOPBACK (1 << 14) // 1=loopback Enabled; 0=Normal Operation
#define GMII_SPEED_SELECT (1 << 13) // 1=100Mbps; 0=10Mbps
#define GMII_AUTONEG (1 << 12) // Auto-negotiation Enable
#define GMII_POWER_DOWN (1 << 11) // 1=Power down 0=Normal operation
#define GMII_ISOLATE (1 << 10) // 1 = Isolates 0 = Normal operation
#define GMII_RESTART_AUTONEG (1 << 9) // 1 = Restart auto-negotiation 0 = Normal operation
#define GMII_DUPLEX_MODE (1 << 8) // 1 = Full duplex operation 0 = Normal operation
#define GMII_COLLISION_TEST (1 << 7) // 1 = Enable COL test; 0 = Disable COL test
//#define GMII_SPEED_SELECT_MSB (1 << 6) // Reserved
// Reserved 6 to 0 // Read as 0, ignore on write
// Bit definitions: GMII_BMSR 0x01 Basic Status
#define GMII_100BASE_T4 (1 << 15) // 100BASE-T4 Capable
#define GMII_100BASE_TX_FD (1 << 14) // 100BASE-TX Full Duplex Capable
#define GMII_100BASE_T4_HD (1 << 13) // 100BASE-TX Half Duplex Capable
#define GMII_10BASE_T_FD (1 << 12) // 10BASE-T Full Duplex Capable
#define GMII_10BASE_T_HD (1 << 11) // 10BASE-T Half Duplex Capable
// Reserved 10 to79 // Read as 0, ignore on write
//#define GMII_EXTEND_STATUS (1 << 8) // 1 = Extend Status Information In Reg 15
// Reserved 7
#define GMII_MF_PREAMB_SUPPR (1 << 6) // MII Frame Preamble Suppression
#define GMII_AUTONEG_COMP (1 << 5) // Auto-negotiation Complete
#define GMII_REMOTE_FAULT (1 << 4) // Remote Fault
#define GMII_AUTONEG_ABILITY (1 << 3) // Auto Configuration Ability
#define GMII_LINK_STATUS (1 << 2) // Link Status
#define GMII_JABBER_DETECT (1 << 1) // Jabber Detect
#define GMII_EXTEND_CAPAB (1 << 0) // Extended Capability
// Bit definitions: GMII_PHYID1 0x02 PHY Idendifier 1
// Bit definitions: GMII_PHYID2 0x03 PHY Idendifier 2
#define GMII_LSB_MASK 0x3F
#define GMII_OUI_MSB 0x0022
#define GMII_OUI_LSB 0x05
// Bit definitions: GMII_ANAR 0x04 Auto_Negotiation Advertisement
// Bit definitions: GMII_ANLPAR 0x05 Auto_negotiation Link Partner Ability
#define GMII_NP (1 << 15) // Next page Indication
// Reserved 7
#define GMII_RF (1 << 13) // Remote Fault
// Reserved 12 // Write as 0, ignore on read
#define GMII_PAUSE_MASK (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
// 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
#define GMII_100T4 (1 << 9) // 100BASE-T4 Support
#define GMII_100TX_FDX (1 << 8) // 100BASE-TX Full Duplex Support
#define GMII_100TX_HDX (1 << 7) // 100BASE-TX Support
#define GMII_10_FDX (1 << 6) // 10BASE-T Full Duplex Support
#define GMII_10_HDX (1 << 5) // 10BASE-T Support
// Selector 4 to 0 // Protocol Selection Bits
#define GMII_AN_IEEE_802_3 0x0001 // [00001] = IEEE 802.3
// Bit definitions: GMII_ANER 0x06 Auto-negotiation Expansion
// Reserved 15 to 5 // Read as 0, ignore on write
#define GMII_PDF (1 << 4) // Local Device Parallel Detection Fault
#define GMII_LP_NP_ABLE (1 << 3) // Link Partner Next Page Able
#define GMII_NP_ABLE (1 << 2) // Local Device Next Page Able
#define GMII_PAGE_RX (1 << 1) // New Page Received
#define GMII_LP_AN_ABLE (1 << 0) // Link Partner Auto-negotiation Able
/**
* \brief Perform a HW initialization to the PHY and set up clocks.
*
* This should be called only once to initialize the PHY pre-settings.
* The PHY address is the reset status of CRS, RXD[3:0] (the GmacPins' pullups).
* The COL pin is used to select MII mode on reset (pulled up for Reduced MII).
* The RXDV pin is used to select test mode on reset (pulled up for test mode).
* The above pins should be predefined for corresponding settings in resetPins.
* The GMAC peripheral pins are configured after the reset is done.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param ul_mck GMAC MCK.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_init(Gmac *p_gmac, uint8_t uc_phy_addr, uint32_t ul_mck);
/**
* \brief Get the Link & speed settings, and automatically set up the GMAC with the
* settings.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
* \param uc_apply_setting_flag Set to 0 to not apply the PHY configurations, else to apply.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_set_link(Gmac *p_gmac, uint8_t uc_phy_addr,
uint8_t uc_apply_setting_flag);
/**
* \brief Issue an auto negotiation of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_auto_negotiate(Gmac *p_gmac, uint8_t uc_phy_addr);
/**
* \brief Issue a SW reset to reset all registers of the PHY.
*
* \param p_gmac Pointer to the GMAC instance.
* \param uc_phy_addr PHY address.
*
* \Return GMAC_OK if successfully, GMAC_TIMEOUT if timeout.
*/
uint8_t ethernet_phy_reset(Gmac *p_gmac, uint8_t uc_phy_addr);
typedef struct xPHY_PROPS {
signed char phy_result;
uint32_t phy_params;
uint32_t phy_stat1;
uint32_t phy_stat2;
unsigned char phy_chn;
} PhyProps_t;
extern PhyProps_t phy_props;
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */

View file

@ -1,721 +0,0 @@
/*
* Handling of Ethernet PHY's
* PHY's communicate with an EMAC either through
* a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
* The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
* shall be treated independently.
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "phyHandling.h"
#define phyMIN_PHY_ADDRESS 0
#define phyMAX_PHY_ADDRESS 31
#if defined( PHY_LS_HIGH_CHECK_TIME_MS ) || defined( PHY_LS_LOW_CHECK_TIME_MS )
#warning please use the new defines with 'ipconfig' prefix
#endif
#ifndef ipconfigPHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still high after 15 seconds of not
receiving packets. */
#define ipconfigPHY_LS_HIGH_CHECK_TIME_MS 15000uL
#endif
#ifndef ipconfigPHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkStatus in the PHY is still low every second. */
#define ipconfigPHY_LS_LOW_CHECK_TIME_MS 1000uL
#endif
/* As the following 3 macro's are OK in most situations, and so they're not
included in 'FreeRTOSIPConfigDefaults.h'.
Users can change their values in the project's 'FreeRTOSIPConfig.h'. */
#ifndef phyPHY_MAX_RESET_TIME_MS
#define phyPHY_MAX_RESET_TIME_MS 1000uL
#endif
#ifndef phyPHY_MAX_NEGOTIATE_TIME_MS
#define phyPHY_MAX_NEGOTIATE_TIME_MS 3000uL
#endif
#ifndef phySHORT_DELAY_MS
#define phySHORT_DELAY_MS 50uL
#endif
/* Naming and numbering of basic PHY registers. */
#define phyREG_00_BMCR 0x00u /* Basic Mode Control Register. */
#define phyREG_01_BMSR 0x01u /* Basic Mode Status Register. */
#define phyREG_02_PHYSID1 0x02u /* PHYS ID 1 */
#define phyREG_03_PHYSID2 0x03u /* PHYS ID 2 */
#define phyREG_04_ADVERTISE 0x04u /* Advertisement control reg */
/* Naming and numbering of extended PHY registers. */
#define PHYREG_10_PHYSTS 0x10u /* 16 PHY status register Offset */
#define phyREG_19_PHYCR 0x19u /* 25 RW PHY Control Register */
#define phyREG_1F_PHYSPCS 0x1Fu /* 31 RW PHY Special Control Status */
/* Bit fields for 'phyREG_00_BMCR', the 'Basic Mode Control Register'. */
#define phyBMCR_FULL_DUPLEX 0x0100u /* Full duplex. */
#define phyBMCR_AN_RESTART 0x0200u /* Auto negotiation restart. */
#define phyBMCR_ISOLATE 0x0400u /* 1 = Isolates 0 = Normal operation. */
#define phyBMCR_AN_ENABLE 0x1000u /* Enable auto negotiation. */
#define phyBMCR_SPEED_100 0x2000u /* Select 100Mbps. */
#define phyBMCR_RESET 0x8000u /* Reset the PHY. */
/* Bit fields for 'phyREG_19_PHYCR', the 'PHY Control Register'. */
#define PHYCR_MDIX_EN 0x8000u /* Enable Auto MDIX. */
#define PHYCR_MDIX_FORCE 0x4000u /* Force MDIX crossed. */
#define phyBMSR_AN_COMPLETE 0x0020u /* Auto-Negotiation process completed */
#define phyBMSR_LINK_STATUS 0x0004u
#define phyPHYSTS_LINK_STATUS 0x0001u /* PHY Link mask */
#define phyPHYSTS_SPEED_STATUS 0x0002u /* PHY Speed mask */
#define phyPHYSTS_DUPLEX_STATUS 0x0004u /* PHY Duplex mask */
/* Bit fields for 'phyREG_1F_PHYSPCS
001 = 10BASE-T half-duplex
101 = 10BASE-T full-duplex
010 = 100BASE-TX half-duplex
110 = 100BASE-TX full-duplex
*/
#define phyPHYSPCS_SPEED_MASK 0x000Cu
#define phyPHYSPCS_SPEED_10 0x0004u
#define phyPHYSPCS_FULL_DUPLEX 0x0010u
/*
* Description of all capabilities that can be advertised to
* the peer (usually a switch or router).
*/
#define phyADVERTISE_CSMA 0x0001u /* Supports IEEE 802.3u: Fast Ethernet at 100 Mbit/s */
#define phyADVERTISE_10HALF 0x0020u /* Try for 10mbps half-duplex. */
#define phyADVERTISE_10FULL 0x0040u /* Try for 10mbps full-duplex. */
#define phyADVERTISE_100HALF 0x0080u /* Try for 100mbps half-duplex. */
#define phyADVERTISE_100FULL 0x0100u /* Try for 100mbps full-duplex. */
#define phyADVERTISE_ALL ( phyADVERTISE_10HALF | phyADVERTISE_10FULL | \
phyADVERTISE_100HALF | phyADVERTISE_100FULL | \
phyADVERTISE_CSMA )
/* Send a reset command to a set of PHY-ports. */
static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
static BaseType_t xHas_1F_PHYSPCS( uint32_t ulPhyID )
{
BaseType_t xResult;
switch( ulPhyID )
{
case PHY_ID_LAN8720:
case PHY_ID_LAN8742A:
case PHY_ID_KSZ8041:
/*
case PHY_ID_KSZ8051: // same ID as 8041
case PHY_ID_KSZ8081: // same ID as 8041
*/
case PHY_ID_KSZ8081MNXIA:
case PHY_ID_KSZ8863:
default:
/* Most PHY's have a 1F_PHYSPCS */
xResult = pdTRUE;
break;
case PHY_ID_DP83848I:
xResult = pdFALSE;
break;
}
return xResult;
}
/*-----------------------------------------------------------*/
static BaseType_t xHas_19_PHYCR( uint32_t ulPhyID )
{
BaseType_t xResult;
switch( ulPhyID )
{
case PHY_ID_LAN8742A:
case PHY_ID_DP83848I:
xResult = pdTRUE;
break;
default:
/* Most PHY's do not have a 19_PHYCR */
xResult = pdFALSE;
break;
}
return xResult;
}
/*-----------------------------------------------------------*/
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite )
{
memset( ( void * )pxPhyObject, '\0', sizeof( *pxPhyObject ) );
pxPhyObject->fnPhyRead = fnPhyRead;
pxPhyObject->fnPhyWrite = fnPhyWrite;
}
/*-----------------------------------------------------------*/
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject )
{
BaseType_t xPhyAddress;
pxPhyObject->xPortCount = 0;
for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ )
{
uint32_t ulLowerID;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID );
/* A valid PHY id can not be all zeros or all ones. */
if( ( ulLowerID != ( uint16_t )~0u ) && ( ulLowerID != ( uint16_t )0u ) )
{
uint32_t ulUpperID;
uint32_t ulPhyID;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_02_PHYSID1, &ulUpperID );
ulPhyID = ( ( ( uint32_t ) ulUpperID ) << 16 ) | ( ulLowerID & 0xFFF0 );
pxPhyObject->ucPhyIndexes[ pxPhyObject->xPortCount ] = xPhyAddress;
pxPhyObject->ulPhyIDs[ pxPhyObject->xPortCount ] = ulPhyID;
pxPhyObject->xPortCount++;
/* See if there is more storage space. */
if( pxPhyObject->xPortCount == ipconfigPHY_MAX_PORTS )
{
break;
}
}
}
if( pxPhyObject->xPortCount > 0 )
{
FreeRTOS_printf( ( "PHY ID %lX\n", pxPhyObject->ulPhyIDs[ 0 ] ) );
}
return pxPhyObject->xPortCount;
}
/*-----------------------------------------------------------*/
/* Send a reset command to a set of PHY-ports. */
static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{
uint32_t ulDoneMask, ulConfig;
TickType_t xRemainingTime;
TimeOut_t xTimer;
BaseType_t xPhyIndex;
/* A bit-mask of PHY ports that are ready. */
ulDoneMask = 0ul;
/* Set the RESET bits high. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Read Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET );
}
xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_RESET_TIME_MS );
vTaskSetTimeOutState( &xTimer );
/* The reset should last less than a second. */
for( ;; )
{
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
if( ( ulConfig & phyBMCR_RESET ) == 0 )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) );
ulDoneMask |= ( 1ul << xPhyIndex );
}
}
if( ulDoneMask == ulPhyMask )
{
break;
}
if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
{
FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
break;
}
/* Block for a while */
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
/* Clear the reset bits. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
if( ( ulDoneMask & ( 1ul << xPhyIndex ) ) == 0uL )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* The reset operation timed out, clear the bit manually. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET );
}
}
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
return ulDoneMask;
}
/*-----------------------------------------------------------*/
BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties )
{
uint32_t ulConfig, ulAdvertise;
BaseType_t xPhyIndex;
if( pxPhyObject->xPortCount < 1 )
{
FreeRTOS_printf( ( "xPhyConfigure: No PHY's detected.\n" ) );
return -1;
}
/* The expected ID for the 'LAN8742A' is 0x0007c130. */
/* The expected ID for the 'LAN8720' is 0x0007c0f0. */
/* The expected ID for the 'DP83848I' is 0x20005C90. */
/* Set advertise register. */
if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) )
{
ulAdvertise = phyADVERTISE_ALL;
/* Reset auto-negotiation capability. */
}
else
{
/* Always select protocol 802.3u. */
ulAdvertise = phyADVERTISE_CSMA;
if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO )
{
if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_100FULL;
}
else
{
ulAdvertise |= phyADVERTISE_10HALF | phyADVERTISE_100HALF;
}
}
else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO )
{
if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 )
{
ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_10HALF;
}
else
{
ulAdvertise |= phyADVERTISE_100FULL | phyADVERTISE_100HALF;
}
}
else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 )
{
if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_100FULL;
}
else
{
ulAdvertise |= phyADVERTISE_100HALF;
}
}
else
{
if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL )
{
ulAdvertise |= phyADVERTISE_10FULL;
}
else
{
ulAdvertise |= phyADVERTISE_10HALF;
}
}
}
/* Send a reset command to a set of PHY-ports. */
xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
/* Write advertise register. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, ulAdvertise );
/*
AN_EN AN1 AN0 Forced Mode
0 0 0 10BASE-T, Half-Duplex
0 0 1 10BASE-T, Full-Duplex
0 1 0 100BASE-TX, Half-Duplex
0 1 1 100BASE-TX, Full-Duplex
AN_EN AN1 AN0 Advertised Mode
1 0 0 10BASE-T, Half/Full-Duplex
1 0 1 100BASE-TX, Half/Full-Duplex
1 1 0 10BASE-T Half-Duplex
100BASE-TX, Half-Duplex
1 1 1 10BASE-T, Half/Full-Duplex
100BASE-TX, Half/Full-Duplex
*/
/* Read Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig );
ulConfig &= ~( phyBMCR_SPEED_100 | phyBMCR_FULL_DUPLEX );
ulConfig |= phyBMCR_AN_ENABLE;
if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 ) || ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) )
{
ulConfig |= phyBMCR_SPEED_100;
}
else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 )
{
ulConfig &= ~phyBMCR_SPEED_100;
}
if( ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) || ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) )
{
ulConfig |= phyBMCR_FULL_DUPLEX;
}
else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_HALF )
{
ulConfig &= ~phyBMCR_FULL_DUPLEX;
}
if( xHas_19_PHYCR( ulPhyID ) )
{
uint32_t ulPhyControl;
/* Read PHY Control register. */
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_19_PHYCR, &ulPhyControl );
/* Clear bits which might get set: */
ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );
if( pxPhyProperties->ucMDI_X == PHY_MDIX_AUTO )
{
ulPhyControl |= PHYCR_MDIX_EN;
}
else if( pxPhyProperties->ucMDI_X == PHY_MDIX_CROSSED )
{
/* Force direct link = Use crossed RJ45 cable. */
ulPhyControl &= ~PHYCR_MDIX_FORCE;
}
else
{
/* Force crossed link = Use direct RJ45 cable. */
ulPhyControl |= PHYCR_MDIX_FORCE;
}
/* update PHY Control Register. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_19_PHYCR, ulPhyControl );
}
FreeRTOS_printf( ( "+TCP: advertise: %04lX config %04lX\n", ulAdvertise, ulConfig ) );
}
/* Keep these values for later use. */
pxPhyObject->ulBCRValue = ulConfig & ~phyBMCR_ISOLATE;
pxPhyObject->ulACRValue = ulAdvertise;
return 0;
}
/*-----------------------------------------------------------*/
/* xPhyFixedValue(): this function is called in case auto-negotiation is disabled.
The caller has set the values in 'xPhyPreferences' (ucDuplex and ucSpeed).
The PHY register phyREG_00_BMCR will be set for every connected PHY that matches
with ulPhyMask. */
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{
BaseType_t xPhyIndex;
uint32_t ulValue, ulBitMask = ( uint32_t )1u;
ulValue = ( uint32_t )0u;
if( pxPhyObject->xPhyPreferences.ucDuplex == PHY_DUPLEX_FULL )
{
ulValue |= phyBMCR_FULL_DUPLEX;
}
if( pxPhyObject->xPhyPreferences.ucSpeed == PHY_SPEED_100 )
{
ulValue |= phyBMCR_SPEED_100;
}
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Enable Auto-Negotiation. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulValue );
}
}
return 0;
}
/*-----------------------------------------------------------*/
/* xPhyStartAutoNegotiation() is the alternative xPhyFixedValue():
It sets the BMCR_AN_RESTART bit and waits for the auto-negotiation completion
( phyBMSR_AN_COMPLETE ). */
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask )
{
uint32_t xPhyIndex, ulDoneMask, ulBitMask;
uint32_t ulPHYLinkStatus, ulRegValue;
TickType_t xRemainingTime;
TimeOut_t xTimer;
if( ulPhyMask == ( uint32_t )0u )
{
return 0;
}
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++ )
{
if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
/* Enable Auto-Negotiation. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, pxPhyObject->ulACRValue);
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART );
}
}
xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( phyPHY_MAX_NEGOTIATE_TIME_MS );
vTaskSetTimeOutState( &xTimer );
ulDoneMask = 0;
/* Wait until the auto-negotiation will be completed */
for( ;; )
{
ulBitMask = ( uint32_t )1u;
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( ulPhyMask & ulBitMask ) != 0lu )
{
if( ( ulDoneMask & ulBitMask ) == 0lu )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue );
if( ( ulRegValue & phyBMSR_AN_COMPLETE ) != 0 )
{
ulDoneMask |= ulBitMask;
}
}
}
}
if( ulPhyMask == ulDoneMask )
{
break;
}
if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE )
{
FreeRTOS_printf( ( "xPhyStartAutoNegotiation: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) );
break;
}
vTaskDelay( pdMS_TO_TICKS( phySHORT_DELAY_MS ) );
}
if( ulDoneMask != ( uint32_t)0u )
{
ulBitMask = ( uint32_t )1u;
pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask );
for( xPhyIndex = 0; xPhyIndex < ( uint32_t ) pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ];
if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u )
{
continue;
}
/* Clear the 'phyBMCR_AN_RESTART' bit. */
pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue );
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue);
if( ( ulRegValue & phyBMSR_LINK_STATUS ) != 0 )
{
ulPHYLinkStatus |= phyBMSR_LINK_STATUS;
pxPhyObject->ulLinkStatusMask |= ulBitMask;
}
else
{
ulPHYLinkStatus &= ~( phyBMSR_LINK_STATUS );
}
if( ulPhyID == PHY_ID_KSZ8081MNXIA )
{
uint32_t ulControlStatus;
pxPhyObject->fnPhyRead( xPhyAddress, 0x1E, &ulControlStatus);
switch( ulControlStatus & 0x07 )
{
case 0x01:
case 0x05:
// [001] = 10BASE-T half-duplex
// [101] = 10BASE-T full-duplex
/* 10 Mbps. */
ulRegValue |= phyPHYSTS_SPEED_STATUS;
break;
case 0x02:
case 0x06:
// [010] = 100BASE-TX half-duplex
// [110] = 100BASE-TX full-duplex
break;
}
switch( ulControlStatus & 0x07 )
{
case 0x05:
case 0x06:
// [101] = 10BASE-T full-duplex
// [110] = 100BASE-TX full-duplex
/* Full duplex. */
ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
break;
case 0x01:
case 0x02:
// [001] = 10BASE-T half-duplex
// [010] = 100BASE-TX half-duplex
break;
}
}
else if( xHas_1F_PHYSPCS( ulPhyID ) )
{
/* 31 RW PHY Special Control Status */
uint32_t ulControlStatus;
pxPhyObject->fnPhyRead( xPhyAddress, phyREG_1F_PHYSPCS, &ulControlStatus);
ulRegValue = 0;
if( ( ulControlStatus & phyPHYSPCS_FULL_DUPLEX ) != 0 )
{
ulRegValue |= phyPHYSTS_DUPLEX_STATUS;
}
if( ( ulControlStatus & phyPHYSPCS_SPEED_MASK ) == phyPHYSPCS_SPEED_10 )
{
ulRegValue |= phyPHYSTS_SPEED_STATUS;
}
}
else
{
/* Read the result of the auto-negotiation. */
pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue);
}
FreeRTOS_printf( ( "Autonego ready: %08lx: %s duplex %u mbit %s status\n",
ulRegValue,
( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half",
( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100,
( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) );
if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u )
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL;
}
else
{
pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_HALF;
}
if( ( ulRegValue & phyPHYSTS_SPEED_STATUS ) != 0 )
{
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_10;
}
else
{
pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100;
}
}
} /* if( ulDoneMask != ( uint32_t)0u ) */
return 0;
}
/*-----------------------------------------------------------*/
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception )
{
uint32_t ulStatus, ulBitMask = 1u;
BaseType_t xPhyIndex;
BaseType_t xNeedCheck = pdFALSE;
if( xHadReception > 0 )
{
/* A packet was received. No need to check for the PHY status now,
but set a timer to check it later on. */
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
if( ( pxPhyObject->ulLinkStatusMask & ulBitMask ) == 0ul )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
xNeedCheck = pdTRUE;
}
}
}
else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE )
{
/* Frequent checking the PHY Link Status can affect for the performance of Ethernet controller.
As long as packets are received, no polling is needed.
Otherwise, polling will be done when the 'xLinkStatusTimer' expires. */
for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 )
{
BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ];
if( pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulStatus ) == 0 )
{
if( !!( pxPhyObject->ulLinkStatusMask & ulBitMask ) != !!( ulStatus & phyBMSR_LINK_STATUS ) )
{
if( ( ulStatus & phyBMSR_LINK_STATUS ) != 0 )
{
pxPhyObject->ulLinkStatusMask |= ulBitMask;
}
else
{
pxPhyObject->ulLinkStatusMask &= ~( ulBitMask );
}
FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) );
xNeedCheck = pdTRUE;
}
}
}
vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) );
if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 )
{
/* The link status is high, so don't poll the PHY too often. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
/* The link status is low, polling may be done more frequently. */
pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS );
}
}
return xNeedCheck;
}
/*-----------------------------------------------------------*/

View file

@ -1,267 +1,267 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Hardware abstraction. */
#include "FreeRTOS_IO.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Driver includes. */
#include "lpc17xx_emac.h"
#include "lpc17xx_pinsel.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
EMAC_CFG_Type Emac_Config;
PINSEL_CFG_Type xPinConfig;
BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Enable Ethernet Pins */
boardCONFIGURE_ENET_PINS( xPinConfig );
Emac_Config.Mode = EMAC_MODE_AUTO;
Emac_Config.pbEMAC_Addr = ucMACAddress;
xStatus = EMAC_Init( &Emac_Config );
LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
if( xStatus != ERROR )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
/* Enable the interrupt and set its priority to the minimum
interrupt priority. */
NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ENET_IRQn );
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
configASSERT( xStatus != ERROR );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xReturn = pdFAIL;
int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
/* Attempt to obtain access to a Tx buffer. */
for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
{
if( EMAC_CheckTransmitIndex() == TRUE )
{
/* Will the data fit in the Tx buffer? */
if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
{
/* Assign the buffer to the Tx descriptor that is now known to
be free. */
EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
/* The EMAC now owns the buffer. */
pxNetworkBuffer->pucBuffer = NULL;
/* Initiate the Tx. */
EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
iptraceNETWORK_INTERFACE_TRANSMIT();
/* The Tx has been initiated. */
xReturn = pdPASS;
}
break;
}
else
{
vTaskDelay( niTX_BUFFER_FREE_WAIT );
}
}
/* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return xReturn;
}
/*-----------------------------------------------------------*/
void ENET_IRQHandler( void )
{
uint32_t ulInterruptCause;
while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
{
/* Clear the interrupt. */
LPC_EMAC->IntClear = ulInterruptCause;
/* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
{
LPC_EMAC->Command |= EMAC_CR_TX_RES;
}
/* Unblock the deferred interrupt handler task if the event was an
Rx. */
if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
{
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
}
}
/* ulInterruptCause is used for convenience here. A context switch is
wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
compiler warning. */
portEND_SWITCHING_ISR( ulInterruptCause );
}
/*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters )
{
size_t xDataLength;
const uint16_t usCRCLength = 4;
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
/* This is not included in the header file for some reason. */
extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore );
for( ;; )
{
/* Wait for the EMAC interrupt to indicate that another packet has been
received. The while() loop is only needed if INCLUDE_vTaskSuspend is
set to 0 in FreeRTOSConfig.h. */
while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
/* At least one packet has been received. */
while( EMAC_CheckReceiveIndex() != FALSE )
{
/* Obtain the length, minus the CRC. The CRC is four bytes
but the length is already minus 1. */
xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
if( xDataLength > 0U )
{
/* Obtain a network buffer to pass this data into the
stack. No storage is required as the network buffer
will point directly to the buffer that already holds
the received data. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
pxNetworkBuffer->xDataLength = xDataLength;
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
/* Data was received and stored. Send a message to the IP
task to let it know. */
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
iptraceNETWORK_INTERFACE_RECEIVE();
}
/* Release the frame. */
EMAC_UpdateRxConsumeIndex();
}
}
}
/*-----------------------------------------------------------*/
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Hardware abstraction. */
#include "FreeRTOS_IO.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Driver includes. */
#include "lpc17xx_emac.h"
#include "lpc17xx_pinsel.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( pdMS_TO_TICKS( 2UL ) )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
static SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
EMAC_CFG_Type Emac_Config;
PINSEL_CFG_Type xPinConfig;
BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Enable Ethernet Pins */
boardCONFIGURE_ENET_PINS( xPinConfig );
Emac_Config.Mode = EMAC_MODE_AUTO;
Emac_Config.pbEMAC_Addr = ucMACAddress;
xStatus = EMAC_Init( &Emac_Config );
LPC_EMAC->IntEnable &= ~( EMAC_INT_TX_DONE );
if( xStatus != ERROR )
{
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
/* Enable the interrupt and set its priority to the minimum
interrupt priority. */
NVIC_SetPriority( ENET_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( ENET_IRQn );
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
configASSERT( xStatus != ERROR );
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xReturn = pdFAIL;
int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );
/* Attempt to obtain access to a Tx buffer. */
for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
{
if( EMAC_CheckTransmitIndex() == TRUE )
{
/* Will the data fit in the Tx buffer? */
if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
{
/* Assign the buffer to the Tx descriptor that is now known to
be free. */
EMAC_SetNextPacketToSend( pxNetworkBuffer->pucBuffer );
/* The EMAC now owns the buffer. */
pxNetworkBuffer->pucBuffer = NULL;
/* Initiate the Tx. */
EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
iptraceNETWORK_INTERFACE_TRANSMIT();
/* The Tx has been initiated. */
xReturn = pdPASS;
}
break;
}
else
{
vTaskDelay( niTX_BUFFER_FREE_WAIT );
}
}
/* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return xReturn;
}
/*-----------------------------------------------------------*/
void ENET_IRQHandler( void )
{
uint32_t ulInterruptCause;
while( ( ulInterruptCause = LPC_EMAC->IntStatus ) != 0 )
{
/* Clear the interrupt. */
LPC_EMAC->IntClear = ulInterruptCause;
/* Clear fatal error conditions. NOTE: The driver does not clear all
errors, only those actually experienced. For future reference, range
errors are not actually errors so can be ignored. */
if( ( ulInterruptCause & EMAC_INT_TX_UNDERRUN ) != 0U )
{
LPC_EMAC->Command |= EMAC_CR_TX_RES;
}
/* Unblock the deferred interrupt handler task if the event was an
Rx. */
if( ( ulInterruptCause & EMAC_INT_RX_DONE ) != 0UL )
{
xSemaphoreGiveFromISR( xEMACRxEventSemaphore, NULL );
}
}
/* ulInterruptCause is used for convenience here. A context switch is
wanted, but coding portEND_SWITCHING_ISR( 1 ) would likely result in a
compiler warning. */
portEND_SWITCHING_ISR( ulInterruptCause );
}
/*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters )
{
size_t xDataLength;
const uint16_t usCRCLength = 4;
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
/* This is not included in the header file for some reason. */
extern uint8_t *EMAC_NextPacketToRead( void );
( void ) pvParameters;
configASSERT( xEMACRxEventSemaphore );
for( ;; )
{
/* Wait for the EMAC interrupt to indicate that another packet has been
received. The while() loop is only needed if INCLUDE_vTaskSuspend is
set to 0 in FreeRTOSConfig.h. */
while( xSemaphoreTake( xEMACRxEventSemaphore, portMAX_DELAY ) == pdFALSE );
/* At least one packet has been received. */
while( EMAC_CheckReceiveIndex() != FALSE )
{
/* Obtain the length, minus the CRC. The CRC is four bytes
but the length is already minus 1. */
xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( usCRCLength - 1U );
if( xDataLength > 0U )
{
/* Obtain a network buffer to pass this data into the
stack. No storage is required as the network buffer
will point directly to the buffer that already holds
the received data. */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( 0, ( TickType_t ) 0 );
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pucBuffer = EMAC_NextPacketToRead();
pxNetworkBuffer->xDataLength = xDataLength;
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
/* Data was received and stored. Send a message to the IP
task to let it know. */
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
iptraceETHERNET_RX_EVENT_LOST();
}
}
else
{
iptraceETHERNET_RX_EVENT_LOST();
}
iptraceNETWORK_INTERFACE_RECEIVE();
}
/* Release the frame. */
EMAC_UpdateRxConsumeIndex();
}
}
}
/*-----------------------------------------------------------*/

View file

@ -1,3 +1,3 @@
NetworkInterface.c:
Requires NXP's LPCOpen library and was developed on an LPC1830 and LPC1835 Xplorer
NetworkInterface.c:
Requires NXP's LPCOpen library and was developed on an LPC1830 and LPC1835 Xplorer
boards from NGX.

View file

@ -1,331 +1,331 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "m480_eth.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
static SemaphoreHandle_t xTXMutex = NULL;
/* The handle of the task that processes Rx packets. The handle is required so
the task can be notified when new packets arrive. */
static TaskHandle_t xRxHanderTask = NULL;
static TimerHandle_t xPhyHandlerTask = NULL;
/*
* A task that processes received frames.
*/
static void prvEMACHandlerTask( void *pvParameters );
static void prvPhyTmrCallback( TimerHandle_t xTimer );
/* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536
#ifdef __ICCARM__
#pragma data_alignment=4
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
#else
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
uint8_t hwaddr[6];
BaseType_t xReturn = pdPASS;
/* Init ETH */
numaker_mac_address(hwaddr);
FreeRTOS_UpdateMACAddress(hwaddr);
FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
/* Enable clock & set EMAC configuration */
/* Enable MAC and DMA transmission and reception */
if( numaker_eth_init(hwaddr) < 0)
{
xReturn = pdFAIL;
} else {
xReturn = pdPASS;
/* Guard against the task being created more than once and the
descriptors being initialized more than once. */
/* Timer task to monitor PHY Link status */
if( xPhyHandlerTask == NULL )
{
xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
configASSERT(xPhyHandlerTask);
xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
configASSERT( xReturn );
}
/* Rx task */
if( xRxHanderTask == NULL )
{
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
configASSERT( xReturn );
}
if( xTXMutex == NULL )
{
xTXMutex = xSemaphoreCreateMutex();
configASSERT( xTXMutex );
}
}
NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
numaker_eth_enable_interrupts();
FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
return xReturn;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
{
uint8_t *buffer=NULL;
// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
{
FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
return pdFALSE;
}
buffer = numaker_eth_get_tx_buf();
if( buffer == NULL )
{
NU_DEBUGF(("Eth TX slots are busy\n"));
return pdFALSE;
}
/* Get exclusive access */
xSemaphoreTake(xTXMutex, portMAX_DELAY);
NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
//SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
/* Call the standard trace macro to log the send event. */
iptraceNETWORK_INTERFACE_TRANSMIT();
if( xReleaseAfterSend != pdFALSE )
{
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
buffer. The Ethernet buffer is therefore no longer needed, and must be
freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
xSemaphoreGive(xTXMutex);
return pdTRUE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
}
}
BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
if( numaker_eth_link_ok() )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
static void prvPhyTmrCallback( TimerHandle_t xTimer )
{
IPStackEvent_t xRxEvent;
static BaseType_t lastLink = pdFAIL;
BaseType_t currLink = xGetPhyLinkStatus();
if( currLink != lastLink )
{
FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
if( !currLink )
{
xRxEvent.eEventType = eNetworkDownEvent;
xSendEventStructToIPTask( &xRxEvent, 0 );
}
lastLink = currLink;
}
}
static void prvEMACHandlerTask( void *pvParameters )
{
TimeOut_t xPhyTime;
TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount;
BaseType_t xResult = 0;
uint32_t ulStatus;
uint16_t dataLength = 0;
uint8_t *buffer = NULL;
NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
IPStackEvent_t xRxEvent;
const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* A possibility to set some additional task properties. */
for( ;; )
{
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 ) );
}
/* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
while(1)
{
/* get received frame */
if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
/* The event was lost because a network buffer was not available.
Call the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
break;
}
/* 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( PACKET_BUFFER_SIZE, 0 );
if( pxBufferDescriptor != NULL )
{
memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
// FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
pxBufferDescriptor->xDataLength = dataLength;
} else {
numaker_eth_rx_next();
iptraceETHERNET_RX_EVENT_LOST();
break;
}
/* 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();
}
numaker_eth_rx_next();
}
numaker_eth_trigger_rx();
}
}
void xNetworkCallback(char event)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
switch (event)
{
case 'R': //For RX event
/* Wakeup the prvEMACHandlerTask. */
if( xRxHanderTask != NULL )
{
vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
break;
case 'T': //For TX event
// ack of tx done, no-op in this stage
break;
default:
break;
}
}
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "m480_eth.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
static SemaphoreHandle_t xTXMutex = NULL;
/* The handle of the task that processes Rx packets. The handle is required so
the task can be notified when new packets arrive. */
static TaskHandle_t xRxHanderTask = NULL;
static TimerHandle_t xPhyHandlerTask = NULL;
/*
* A task that processes received frames.
*/
static void prvEMACHandlerTask( void *pvParameters );
static void prvPhyTmrCallback( TimerHandle_t xTimer );
/* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536
#ifdef __ICCARM__
#pragma data_alignment=4
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ]
#else
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ((aligned(4)));
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
uint8_t hwaddr[6];
BaseType_t xReturn = pdPASS;
/* Init ETH */
numaker_mac_address(hwaddr);
FreeRTOS_UpdateMACAddress(hwaddr);
FreeRTOS_printf( ("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]) );
/* Enable clock & set EMAC configuration */
/* Enable MAC and DMA transmission and reception */
if( numaker_eth_init(hwaddr) < 0)
{
xReturn = pdFAIL;
} else {
xReturn = pdPASS;
/* Guard against the task being created more than once and the
descriptors being initialized more than once. */
/* Timer task to monitor PHY Link status */
if( xPhyHandlerTask == NULL )
{
xPhyHandlerTask = xTimerCreate( "TimerPhy", pdMS_TO_TICKS( 1000 ), pdTRUE, 0, prvPhyTmrCallback );
configASSERT(xPhyHandlerTask);
xReturn = xTimerStart( xPhyHandlerTask, 0 ) ;
configASSERT( xReturn );
}
/* Rx task */
if( xRxHanderTask == NULL )
{
xReturn = xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xRxHanderTask );
configASSERT( xReturn );
}
if( xTXMutex == NULL )
{
xTXMutex = xSemaphoreCreateMutex();
configASSERT( xTXMutex );
}
}
NVIC_SetPriority( EMAC_RX_IRQn, configMAC_INTERRUPT_PRIORITY );
NVIC_SetPriority( EMAC_TX_IRQn, configMAC_INTERRUPT_PRIORITY );
numaker_eth_enable_interrupts();
FreeRTOS_printf( ("ETH-RX priority:%d\n",NVIC_GetPriority( EMAC_RX_IRQn)) );
return xReturn;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend )
{
uint8_t *buffer=NULL;
// FreeRTOS_printf(("<-- dataLength=%d\n",pxDescriptor->xDataLength));
if( pxDescriptor->xDataLength >= PACKET_BUFFER_SIZE )
{
FreeRTOS_printf(("TX buffer length %d over %d\n", pxDescriptor->xDataLength, PACKET_BUFFER_SIZE));
return pdFALSE;
}
buffer = numaker_eth_get_tx_buf();
if( buffer == NULL )
{
NU_DEBUGF(("Eth TX slots are busy\n"));
return pdFALSE;
}
/* Get exclusive access */
xSemaphoreTake(xTXMutex, portMAX_DELAY);
NU_DEBUGF(("%s ... buffer=0x%x\r\n",__FUNCTION__, buffer));
//SendData: pt = pxDescriptor->pucBuffer, length = pxDescriptor->xDataLength
memcpy(buffer, pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength);
numaker_eth_trigger_tx(pxDescriptor->xDataLength, NULL);
/* Call the standard trace macro to log the send event. */
iptraceNETWORK_INTERFACE_TRANSMIT();
if( xReleaseAfterSend != pdFALSE )
{
/* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet
buffer. The Ethernet buffer is therefore no longer needed, and must be
freed for re-use. */
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
xSemaphoreGive(xTXMutex);
return pdTRUE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
}
}
BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
if( numaker_eth_link_ok() )
{
xReturn = pdPASS;
}
else
{
xReturn = pdFAIL;
}
return xReturn;
}
static void prvPhyTmrCallback( TimerHandle_t xTimer )
{
IPStackEvent_t xRxEvent;
static BaseType_t lastLink = pdFAIL;
BaseType_t currLink = xGetPhyLinkStatus();
if( currLink != lastLink )
{
FreeRTOS_printf(("PHY Link %s\n", (currLink) ? "Up" : "Down"));
if( !currLink )
{
xRxEvent.eEventType = eNetworkDownEvent;
xSendEventStructToIPTask( &xRxEvent, 0 );
}
lastLink = currLink;
}
}
static void prvEMACHandlerTask( void *pvParameters )
{
TimeOut_t xPhyTime;
TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount;
BaseType_t xResult = 0;
uint32_t ulStatus;
uint16_t dataLength = 0;
uint8_t *buffer = NULL;
NetworkBufferDescriptor_t *pxBufferDescriptor = NULL;
IPStackEvent_t xRxEvent;
const TickType_t xBlockTime = pdMS_TO_TICKS( 5000ul );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* A possibility to set some additional task properties. */
for( ;; )
{
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 ) );
}
/* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
while(1)
{
/* get received frame */
if ( numaker_eth_get_rx_buf(&dataLength, &buffer) != 0) {
/* The event was lost because a network buffer was not available.
Call the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
break;
}
/* 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( PACKET_BUFFER_SIZE, 0 );
if( pxBufferDescriptor != NULL )
{
memcpy( pxBufferDescriptor->pucEthernetBuffer, buffer, dataLength );
// FreeRTOS_printf(("--> dataLength=%d\n",dataLength));
pxBufferDescriptor->xDataLength = dataLength;
} else {
numaker_eth_rx_next();
iptraceETHERNET_RX_EVENT_LOST();
break;
}
/* 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();
}
numaker_eth_rx_next();
}
numaker_eth_trigger_rx();
}
}
void xNetworkCallback(char event)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
switch (event)
{
case 'R': //For RX event
/* Wakeup the prvEMACHandlerTask. */
if( xRxHanderTask != NULL )
{
vTaskNotifyGiveFromISR( xRxHanderTask, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
break;
case 'T': //For TX event
// ack of tx done, no-op in this stage
break;
default:
break;
}
}

View file

@ -1,448 +1,448 @@
/**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "FreeRTOS.h"
#include "list.h"
#include "FreeRTOS_IP.h"
#include "m480_eth.h"
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
#ifdef __ICCARM__
#pragma data_alignment=4
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
#else
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
#endif
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
// Assume we want to set each tick to 100ns.
// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)
{
EMAC->MIIMDAT = val;
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
}
static uint16_t mdio_read(uint8_t addr, uint8_t reg)
{
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
return(EMAC->MIIMDAT);
}
static int reset_phy(void)
{
uint16_t reg;
uint32_t delayCnt;
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
delayCnt = 2000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
break;
}
if(delayCnt == 0) {
NU_DEBUGF(("Reset phy failed\n"));
return(-1);
}
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
ADVERTISE_10HALF |
ADVERTISE_10FULL |
ADVERTISE_100HALF |
ADVERTISE_100FULL);
reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
delayCnt = 200000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
break;
}
if(delayCnt == 0) {
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
return(-1);
} else {
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
if(reg & ADVERTISE_100FULL) {
NU_DEBUGF(("100 full\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
} else if(reg & ADVERTISE_100HALF) {
NU_DEBUGF(("100 half\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
} else if(reg & ADVERTISE_10FULL) {
NU_DEBUGF(("10 full\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
} else {
NU_DEBUGF(("10 half\n"));
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
}
}
FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));
FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));
return(0);
}
static void init_tx_desc(void)
{
uint32_t i;
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
tx_desc[i].buf = &tx_buf[i][0];
tx_desc[i].status2 = 0;
tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->TXDSA = (unsigned int)&tx_desc[0];
return;
}
static void init_rx_desc(void)
{
uint32_t i;
cur_rx_desc_ptr = &rx_desc[0];
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
rx_desc[i].status1 = OWNERSHIP_EMAC;
rx_desc[i].buf = &rx_buf[i][0];
rx_desc[i].status2 = 0;
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->RXDSA = (unsigned int)&rx_desc[0];
return;
}
void numaker_set_mac_addr(uint8_t *addr)
{
EMAC->CAM0M = (addr[0] << 24) |
(addr[1] << 16) |
(addr[2] << 8) |
addr[3];
EMAC->CAM0L = (addr[4] << 24) |
(addr[5] << 16);
}
static void __eth_clk_pin_init()
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable IP clock */
CLK_EnableModuleClock(EMAC_MODULE);
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
/* Update System Core Clock */
SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
// Configure RMII pins
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
// Enable high slew rate on all RMII TX output pins
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
/* Lock protected registers */
SYS_LockReg();
}
int numaker_eth_init(uint8_t *mac_addr)
{
int ret = 0;
// init CLK & pins
__eth_clk_pin_init();
// Reset MAC
EMAC->CTL = EMAC_CTL_RST_Msk;
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
init_tx_desc();
init_rx_desc();
numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
/* Configure the MAC interrupt enable register. */
EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk |
EMAC_INTEN_RXGDIEN_Msk |
EMAC_INTEN_TXCPIEN_Msk |
EMAC_INTEN_RXBEIEN_Msk |
EMAC_INTEN_TXBEIEN_Msk |
EMAC_INTEN_RDUIEN_Msk |
EMAC_INTEN_TSALMIEN_Msk |
EMAC_INTEN_WOLIEN_Msk;
/* Configure the MAC control register. */
EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
/* Accept packets for us and all broadcast and multicast packets */
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
EMAC_CAMCTL_AMP_Msk |
EMAC_CAMCTL_ABP_Msk;
EMAC->CAMEN = 1; // Enable CAM entry 0
ret= reset_phy();
EMAC_ENABLE_RX();
EMAC_ENABLE_TX();
return ret;
}
void ETH_halt(void)
{
EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
}
unsigned int m_status;
void EMAC_RX_IRQHandler(void)
{
// NU_DEBUGF(("%s ... \r\n", __FUNCTION__));
m_status = EMAC->INTSTS & 0xFFFF;
EMAC->INTSTS = m_status;
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
NU_DEBUGF(("RX descriptor corrupted \r\n"));
//return;
}
// FIX ME: for rx-event, to ack rx_isr into event queue
xNetworkCallback('R');
}
void numaker_eth_trigger_rx(void)
{
ETH_TRIGGER_RX();
}
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
{
unsigned int cur_entry, status;
cur_entry = EMAC->CRXDSA;
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
return -1;
status = cur_rx_desc_ptr->status1;
if(status & OWNERSHIP_EMAC)
return -1;
if (status & RXFD_RXGD) {
*buf = cur_rx_desc_ptr->buf;
*len = status & 0xFFFF;
}
return 0;
}
void numaker_eth_rx_next(void)
{
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
}
void EMAC_TX_IRQHandler(void)
{
unsigned int cur_entry, status;
status = EMAC->INTSTS & 0xFFFF0000;
EMAC->INTSTS = status;
if(status & EMAC_INTSTS_TXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
return;
}
cur_entry = EMAC->CTXDSA;
while (cur_entry != (uint32_t)fin_tx_desc_ptr) {
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
}
// FIX ME: for tx-event, no-op at this stage
xNetworkCallback('T');
}
uint8_t *numaker_eth_get_tx_buf(void)
{
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
return(NULL);
else
return(cur_tx_desc_ptr->buf);
}
void numaker_eth_trigger_tx(uint16_t length, void *p)
{
struct eth_descriptor volatile *desc;
cur_tx_desc_ptr->status2 = (unsigned int)length;
desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
cur_tx_desc_ptr = desc;
ETH_TRIGGER_TX();
}
int numaker_eth_link_ok(void)
{
/* first, a dummy read to latch */
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
return 1;
return 0;
}
//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
//{
// nu_eth_txrx_cb = eth_cb;
// nu_userData = userData;
//}
// Provide ethernet devices with a semi-unique MAC address
void numaker_mac_address(uint8_t *mac)
{
uint32_t uID1;
// Fetch word 0
uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
// Fetch word 1
// we only want bottom 16 bits of word1 (MAC bits 32-47)
// and bit 9 forced to 1, bit 8 forced to 0
// Locally administered MAC, reduced conflicts
// http://en.wikipedia.org/wiki/MAC_address
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
{
// with a semi-unique MAC address from the UUID
/* Enable FMC ISP function */
SYS_UnlockReg();
FMC_Open();
// = FMC_ReadUID(0);
uID1 = FMC_ReadUID(1);
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
/* Disable FMC ISP function */
FMC_Close();
/* Lock protected registers */
SYS_LockReg();
}
word1 |= 0x00000200;
word1 &= 0x0000FEFF;
mac[0] = (word1 & 0x0000ff00) >> 8;
mac[1] = (word1 & 0x000000ff);
mac[2] = (word0 & 0xff000000) >> 24;
mac[3] = (word0 & 0x00ff0000) >> 16;
mac[4] = (word0 & 0x0000ff00) >> 8;
mac[5] = (word0 & 0x000000ff);
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
}
void numaker_eth_enable_interrupts(void) {
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk ;
NVIC_EnableIRQ(EMAC_RX_IRQn);
NVIC_EnableIRQ(EMAC_TX_IRQn);
}
void numaker_eth_disable_interrupts(void) {
NVIC_DisableIRQ(EMAC_RX_IRQn);
NVIC_DisableIRQ(EMAC_TX_IRQn);
}
/**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "FreeRTOS.h"
#include "list.h"
#include "FreeRTOS_IP.h"
#include "m480_eth.h"
#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0)
#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON;}while(0)
#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0)
#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON;}while(0)
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
#ifdef __ICCARM__
#pragma data_alignment=4
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM];
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM];
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE];
#else
struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM] __attribute__ ((aligned(4)));
uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE] __attribute__ ((aligned(4)));
#endif
struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr;
// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
// Assume we want to set each tick to 100ns.
// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val)
{
EMAC->MIIMDAT = val;
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
}
static uint16_t mdio_read(uint8_t addr, uint8_t reg)
{
EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
return(EMAC->MIIMDAT);
}
static int reset_phy(void)
{
uint16_t reg;
uint32_t delayCnt;
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET);
delayCnt = 2000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0)
break;
}
if(delayCnt == 0) {
NU_DEBUGF(("Reset phy failed\n"));
return(-1);
}
mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA |
ADVERTISE_10HALF |
ADVERTISE_10FULL |
ADVERTISE_100HALF |
ADVERTISE_100FULL);
reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR);
mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART);
delayCnt = 200000;
while(delayCnt-- > 0) {
if((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
== (BMSR_ANEGCOMPLETE | BMSR_LSTATUS))
break;
}
if(delayCnt == 0) {
NU_DEBUGF(("AN failed. Set to 100 FULL\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
return(-1);
} else {
reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA);
if(reg & ADVERTISE_100FULL) {
NU_DEBUGF(("100 full\n"));
EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
} else if(reg & ADVERTISE_100HALF) {
NU_DEBUGF(("100 half\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk;
} else if(reg & ADVERTISE_10FULL) {
NU_DEBUGF(("10 full\n"));
EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk;
} else {
NU_DEBUGF(("10 half\n"));
EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk);
}
}
FreeRTOS_printf(("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)));
FreeRTOS_printf(("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)));
return(0);
}
static void init_tx_desc(void)
{
uint32_t i;
cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0];
for(i = 0; i < TX_DESCRIPTOR_NUM; i++) {
tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN;
tx_desc[i].buf = &tx_buf[i][0];
tx_desc[i].status2 = 0;
tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->TXDSA = (unsigned int)&tx_desc[0];
return;
}
static void init_rx_desc(void)
{
uint32_t i;
cur_rx_desc_ptr = &rx_desc[0];
for(i = 0; i < RX_DESCRIPTOR_NUM; i++) {
rx_desc[i].status1 = OWNERSHIP_EMAC;
rx_desc[i].buf = &rx_buf[i][0];
rx_desc[i].status2 = 0;
rx_desc[i].next = &rx_desc[(i + 1) % TX_DESCRIPTOR_NUM];
}
EMAC->RXDSA = (unsigned int)&rx_desc[0];
return;
}
void numaker_set_mac_addr(uint8_t *addr)
{
EMAC->CAM0M = (addr[0] << 24) |
(addr[1] << 16) |
(addr[2] << 8) |
addr[3];
EMAC->CAM0L = (addr[4] << 24) |
(addr[5] << 16);
}
static void __eth_clk_pin_init()
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable IP clock */
CLK_EnableModuleClock(EMAC_MODULE);
// Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH
CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127));
/* Update System Core Clock */
SystemCoreClockUpdate();
/*---------------------------------------------------------------------------------------------------------*/
/* Init I/O Multi-function */
/*---------------------------------------------------------------------------------------------------------*/
// Configure RMII pins
SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk);
SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV;
SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk);
SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0;
SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk;
SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK;
SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk |
SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk);
SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC |
SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO |
SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 |
SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 |
SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN;
// Enable high slew rate on all RMII TX output pins
PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) |
(GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos);
/* Lock protected registers */
SYS_LockReg();
}
int numaker_eth_init(uint8_t *mac_addr)
{
int ret = 0;
// init CLK & pins
__eth_clk_pin_init();
// Reset MAC
EMAC->CTL = EMAC_CTL_RST_Msk;
while(EMAC->CTL & EMAC_CTL_RST_Msk) {}
init_tx_desc();
init_rx_desc();
numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc...
/* Configure the MAC interrupt enable register. */
EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk |
EMAC_INTEN_RXGDIEN_Msk |
EMAC_INTEN_TXCPIEN_Msk |
EMAC_INTEN_RXBEIEN_Msk |
EMAC_INTEN_TXBEIEN_Msk |
EMAC_INTEN_RDUIEN_Msk |
EMAC_INTEN_TSALMIEN_Msk |
EMAC_INTEN_WOLIEN_Msk;
/* Configure the MAC control register. */
EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk;
/* Accept packets for us and all broadcast and multicast packets */
EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
EMAC_CAMCTL_AMP_Msk |
EMAC_CAMCTL_ABP_Msk;
EMAC->CAMEN = 1; // Enable CAM entry 0
ret= reset_phy();
EMAC_ENABLE_RX();
EMAC_ENABLE_TX();
return ret;
}
void ETH_halt(void)
{
EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk);
}
unsigned int m_status;
void EMAC_RX_IRQHandler(void)
{
// NU_DEBUGF(("%s ... \r\n", __FUNCTION__));
m_status = EMAC->INTSTS & 0xFFFF;
EMAC->INTSTS = m_status;
if (m_status & EMAC_INTSTS_RXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
NU_DEBUGF(("RX descriptor corrupted \r\n"));
//return;
}
// FIX ME: for rx-event, to ack rx_isr into event queue
xNetworkCallback('R');
}
void numaker_eth_trigger_rx(void)
{
ETH_TRIGGER_RX();
}
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf)
{
unsigned int cur_entry, status;
cur_entry = EMAC->CRXDSA;
if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) // cur_entry may equal to cur_rx_desc_ptr if RDU occures
return -1;
status = cur_rx_desc_ptr->status1;
if(status & OWNERSHIP_EMAC)
return -1;
if (status & RXFD_RXGD) {
*buf = cur_rx_desc_ptr->buf;
*len = status & 0xFFFF;
}
return 0;
}
void numaker_eth_rx_next(void)
{
cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC;
cur_rx_desc_ptr = cur_rx_desc_ptr->next;
}
void EMAC_TX_IRQHandler(void)
{
unsigned int cur_entry, status;
status = EMAC->INTSTS & 0xFFFF0000;
EMAC->INTSTS = status;
if(status & EMAC_INTSTS_TXBEIF_Msk) {
// Shouldn't goes here, unless descriptor corrupted
return;
}
cur_entry = EMAC->CTXDSA;
while (cur_entry != (uint32_t)fin_tx_desc_ptr) {
fin_tx_desc_ptr = fin_tx_desc_ptr->next;
}
// FIX ME: for tx-event, no-op at this stage
xNetworkCallback('T');
}
uint8_t *numaker_eth_get_tx_buf(void)
{
if(cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC)
return(NULL);
else
return(cur_tx_desc_ptr->buf);
}
void numaker_eth_trigger_tx(uint16_t length, void *p)
{
struct eth_descriptor volatile *desc;
cur_tx_desc_ptr->status2 = (unsigned int)length;
desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr
cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC;
cur_tx_desc_ptr = desc;
ETH_TRIGGER_TX();
}
int numaker_eth_link_ok(void)
{
/* first, a dummy read to latch */
mdio_read(CONFIG_PHY_ADDR, MII_BMSR);
if(mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS)
return 1;
return 0;
}
//void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData)
//{
// nu_eth_txrx_cb = eth_cb;
// nu_userData = userData;
//}
// Provide ethernet devices with a semi-unique MAC address
void numaker_mac_address(uint8_t *mac)
{
uint32_t uID1;
// Fetch word 0
uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800
// Fetch word 1
// we only want bottom 16 bits of word1 (MAC bits 32-47)
// and bit 9 forced to 1, bit 8 forced to 0
// Locally administered MAC, reduced conflicts
// http://en.wikipedia.org/wiki/MAC_address
uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800
if( word0 == 0xFFFFFFFF ) // Not burn any mac address at 1st 2 words of Data Flash
{
// with a semi-unique MAC address from the UUID
/* Enable FMC ISP function */
SYS_UnlockReg();
FMC_Open();
// = FMC_ReadUID(0);
uID1 = FMC_ReadUID(1);
word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8;
word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF)<<12) | (FMC_ReadUID(2) & 0xFFF);
/* Disable FMC ISP function */
FMC_Close();
/* Lock protected registers */
SYS_LockReg();
}
word1 |= 0x00000200;
word1 &= 0x0000FEFF;
mac[0] = (word1 & 0x0000ff00) >> 8;
mac[1] = (word1 & 0x000000ff);
mac[2] = (word0 & 0xff000000) >> 24;
mac[3] = (word0 & 0x00ff0000) >> 16;
mac[4] = (word0 & 0x0000ff00) >> 8;
mac[5] = (word0 & 0x000000ff);
NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]));
}
void numaker_eth_enable_interrupts(void) {
EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk |
EMAC_INTEN_TXIEN_Msk ;
NVIC_EnableIRQ(EMAC_RX_IRQn);
NVIC_EnableIRQ(EMAC_TX_IRQn);
}
void numaker_eth_disable_interrupts(void) {
NVIC_DisableIRQ(EMAC_RX_IRQn);
NVIC_DisableIRQ(EMAC_TX_IRQn);
}

View file

@ -1,164 +1,164 @@
/**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "M480.h"
#ifndef _M480_ETH_
#define _M480_ETH_
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x007f /* Unused... */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x07c0 /* Unused... */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_RESV 0x1c00 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors
#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors
#define PACKET_BUFFER_SIZE 1520
#define CONFIG_PHY_ADDR 1
// Frame Descriptor's Owner bit
#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
// Rx Frame Descriptor Status
#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
// Tx Frame Descriptor's Control bits
#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
#define TXFD_INTEN 0x04 // Interrupt Enable
#define TXFD_CRCAPP 0x02 // Append CRC
#define TXFD_PADEN 0x01 // Padding Enable
// Tx Frame Descriptor Status
#define TXFD_TXCP 0x00080000 // Transmission Completion
#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
// Tx/Rx buffer descriptor structure
struct eth_descriptor;
struct eth_descriptor {
uint32_t status1;
uint8_t *buf;
uint32_t status2;
struct eth_descriptor *next;
#ifdef TIME_STAMPING
uint32_t backup1;
uint32_t backup2;
uint32_t reserved1;
uint32_t reserved2;
#endif
};
#ifdef TIME_STAMPING
#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
s32_t ETH_settime(u32_t sec, u32_t nsec);
s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
s32_t ETH_adjtimex(int ppm);
void ETH_setinc(void);
#endif
#ifdef NU_TRACE
#define NU_DEBUGF(x) { printf x; }
#else
#define NU_DEBUGF(x)
#endif
void numaker_set_mac_addr(uint8_t *addr);
int numaker_eth_init(uint8_t *mac_addr);
uint8_t *numaker_eth_get_tx_buf(void);
void numaker_eth_trigger_tx(uint16_t length, void *p);
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);
void numaker_eth_rx_next(void);
void numaker_eth_trigger_rx(void);
int numaker_eth_link_ok(void);
void numaker_mac_address(uint8_t *mac);
void numaker_eth_enable_interrupts(void);
void numaker_eth_disable_interrupts(void);
#endif /* _M480_ETH_ */
/**************************************************************************//**
* @copyright (C) 2019 Nuvoton Technology Corp. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of Nuvoton Technology Corp. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
#include "M480.h"
#ifndef _M480_ETH_
#define _M480_ETH_
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x007f /* Unused... */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x07c0 /* Unused... */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_RESV 0x1c00 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define RX_DESCRIPTOR_NUM 4 //8 // Max Number of Rx Frame Descriptors
#define TX_DESCRIPTOR_NUM 2 //4 // Max number of Tx Frame Descriptors
#define PACKET_BUFFER_SIZE 1520
#define CONFIG_PHY_ADDR 1
// Frame Descriptor's Owner bit
#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC
//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU
// Rx Frame Descriptor Status
#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received
#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available
// Tx Frame Descriptor's Control bits
#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable
#define TXFD_INTEN 0x04 // Interrupt Enable
#define TXFD_CRCAPP 0x02 // Append CRC
#define TXFD_PADEN 0x01 // Padding Enable
// Tx Frame Descriptor Status
#define TXFD_TXCP 0x00080000 // Transmission Completion
#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available
// Tx/Rx buffer descriptor structure
struct eth_descriptor;
struct eth_descriptor {
uint32_t status1;
uint8_t *buf;
uint32_t status2;
struct eth_descriptor *next;
#ifdef TIME_STAMPING
uint32_t backup1;
uint32_t backup2;
uint32_t reserved1;
uint32_t reserved2;
#endif
};
#ifdef TIME_STAMPING
#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0)
#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0)
s32_t ETH_settime(u32_t sec, u32_t nsec);
s32_t ETH_gettime(u32_t *sec, u32_t *nsec);
s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec);
s32_t ETH_adjtimex(int ppm);
void ETH_setinc(void);
#endif
#ifdef NU_TRACE
#define NU_DEBUGF(x) { printf x; }
#else
#define NU_DEBUGF(x)
#endif
void numaker_set_mac_addr(uint8_t *addr);
int numaker_eth_init(uint8_t *mac_addr);
uint8_t *numaker_eth_get_tx_buf(void);
void numaker_eth_trigger_tx(uint16_t length, void *p);
int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf);
void numaker_eth_rx_next(void);
void numaker_eth_trigger_rx(void);
int numaker_eth_link_ok(void);
void numaker_mac_address(uint8_t *mac);
void numaker_eth_enable_interrupts(void);
void numaker_eth_disable_interrupts(void);
#endif /* _M480_ETH_ */

View file

@ -1,10 +1,10 @@
Network drivers are provided as examples only, and do not form part of the
FreeRTOS+TCP stack itself. They:
+ May be based on driver code provided by the chip vendors,
+ May not have been tested in all possible configurations,
+ Will not necessarily be optimised.
+ May have a dependency on a particular PHY part number.
+ May not necessarily comply with any particular coding standard.
+ May have dependencies on chip company libraries.
+ May include other hardware board dependencies.
Network drivers are provided as examples only, and do not form part of the
FreeRTOS+TCP stack itself. They:
+ May be based on driver code provided by the chip vendors,
+ May not have been tested in all possible configurations,
+ Will not necessarily be optimised.
+ May have a dependency on a particular PHY part number.
+ May not necessarily comply with any particular coding standard.
+ May have dependencies on chip company libraries.
+ May include other hardware board dependencies.

View file

@ -1,177 +1,177 @@
/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : ether_callback.c
* Version : ----
* Description : This module solves all the world's problems
***********************************************************************************************************************/
/**********************************************************************************************************************
* History : DD.MM.YYYY Version Description
* : 05.01.2015 ---- Clean up source code.
***********************************************************************************************************************/
/***********************************************************************************************************************
Includes <System Includes> , "Project Includes"
***********************************************************************************************************************/
#include "r_ether_rx_if.h"
/***********************************************************************************************************************
Private global variables and functions
***********************************************************************************************************************/
int32_t callback_ether_regist(void);
void callback_ether(void * pparam);
static void callback_wakeon_lan(uint32_t channel);
static void callback_link_on(uint32_t channel);
static void callback_link_off(uint32_t channel);
volatile uint8_t pause_enable = ETHER_FLAG_OFF;
volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX];
volatile uint8_t link_detect[ETHER_CHANNEL_MAX];
void EINT_Trig_isr(void *);
/*
* When that Link Status changes, the following function will be called:
*/
void prvLinkStatusChange( BaseType_t xStatus );
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Regist of callback function
* Arguments : -
* Return Value : 0: success, -1:failed
***********************************************************************************************************************/
int32_t callback_ether_regist(void)
{
ether_param_t param;
ether_cb_t cb_func;
int32_t ret;
/* Set the callback function (LAN cable connect/disconnect event) */
cb_func.pcb_func = &callback_ether;
param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);
if (ETHER_SUCCESS != ret)
{
return -1;
}
/* Set the callback function (Ether interrupt event) */
cb_func.pcb_int_hnd = &EINT_Trig_isr;
param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);
if (ETHER_SUCCESS != ret)
{
return -1;
}
return 0;
} /* End of function callback_ether_regist() */
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Sample of the callback function
* Arguments : pparam -
*
* Return Value : none
***********************************************************************************************************************/
void callback_ether(void * pparam)
{
ether_cb_arg_t * pdecode;
uint32_t channel;
pdecode = (ether_cb_arg_t *)pparam;
channel = pdecode->channel; /* Get Ethernet channel number */
switch (pdecode->event_id)
{
/* Callback function that notifies user to have detected magic packet. */
case ETHER_CB_EVENT_ID_WAKEON_LAN:
callback_wakeon_lan(channel);
break;
/* Callback function that notifies user to have become Link up. */
case ETHER_CB_EVENT_ID_LINK_ON:
callback_link_on(channel);
break;
/* Callback function that notifies user to have become Link down. */
case ETHER_CB_EVENT_ID_LINK_OFF:
callback_link_off(channel);
break;
default:
break;
}
} /* End of function callback_ether() */
/***********************************************************************************************************************
* Function Name: callback_wakeon_lan
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_wakeon_lan(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
magic_packet_detect[channel] = 1;
/* Please add necessary processing when magic packet is detected. */
}
} /* End of function callback_wakeon_lan() */
/***********************************************************************************************************************
* Function Name: callback_link_on
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_on(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
link_detect[channel] = ETHER_FLAG_ON_LINK_ON;
/* Please add necessary processing when becoming Link up. */
prvLinkStatusChange( 1 );
}
} /* End of function callback_link_on() */
/***********************************************************************************************************************
* Function Name: callback_link_off
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_off(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;
/* Please add necessary processing when becoming Link down. */
prvLinkStatusChange( 0 );
}
} /* End of function ether_cb_link_off() */
/* End of File */
/***********************************************************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
* other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
* applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
* EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
* SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
* SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
* this software. By using this software, you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
*
* Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
***********************************************************************************************************************/
/***********************************************************************************************************************
* File Name : ether_callback.c
* Version : ----
* Description : This module solves all the world's problems
***********************************************************************************************************************/
/**********************************************************************************************************************
* History : DD.MM.YYYY Version Description
* : 05.01.2015 ---- Clean up source code.
***********************************************************************************************************************/
/***********************************************************************************************************************
Includes <System Includes> , "Project Includes"
***********************************************************************************************************************/
#include "r_ether_rx_if.h"
/***********************************************************************************************************************
Private global variables and functions
***********************************************************************************************************************/
int32_t callback_ether_regist(void);
void callback_ether(void * pparam);
static void callback_wakeon_lan(uint32_t channel);
static void callback_link_on(uint32_t channel);
static void callback_link_off(uint32_t channel);
volatile uint8_t pause_enable = ETHER_FLAG_OFF;
volatile uint8_t magic_packet_detect[ETHER_CHANNEL_MAX];
volatile uint8_t link_detect[ETHER_CHANNEL_MAX];
void EINT_Trig_isr(void *);
/*
* When that Link Status changes, the following function will be called:
*/
void prvLinkStatusChange( BaseType_t xStatus );
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Regist of callback function
* Arguments : -
* Return Value : 0: success, -1:failed
***********************************************************************************************************************/
int32_t callback_ether_regist(void)
{
ether_param_t param;
ether_cb_t cb_func;
int32_t ret;
/* Set the callback function (LAN cable connect/disconnect event) */
cb_func.pcb_func = &callback_ether;
param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_CALLBACK, param);
if (ETHER_SUCCESS != ret)
{
return -1;
}
/* Set the callback function (Ether interrupt event) */
cb_func.pcb_int_hnd = &EINT_Trig_isr;
param.ether_callback = cb_func;
ret = R_ETHER_Control(CONTROL_SET_INT_HANDLER, param);
if (ETHER_SUCCESS != ret)
{
return -1;
}
return 0;
} /* End of function callback_ether_regist() */
/***********************************************************************************************************************
* Function Name: callback_ether
* Description : Sample of the callback function
* Arguments : pparam -
*
* Return Value : none
***********************************************************************************************************************/
void callback_ether(void * pparam)
{
ether_cb_arg_t * pdecode;
uint32_t channel;
pdecode = (ether_cb_arg_t *)pparam;
channel = pdecode->channel; /* Get Ethernet channel number */
switch (pdecode->event_id)
{
/* Callback function that notifies user to have detected magic packet. */
case ETHER_CB_EVENT_ID_WAKEON_LAN:
callback_wakeon_lan(channel);
break;
/* Callback function that notifies user to have become Link up. */
case ETHER_CB_EVENT_ID_LINK_ON:
callback_link_on(channel);
break;
/* Callback function that notifies user to have become Link down. */
case ETHER_CB_EVENT_ID_LINK_OFF:
callback_link_off(channel);
break;
default:
break;
}
} /* End of function callback_ether() */
/***********************************************************************************************************************
* Function Name: callback_wakeon_lan
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_wakeon_lan(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
magic_packet_detect[channel] = 1;
/* Please add necessary processing when magic packet is detected. */
}
} /* End of function callback_wakeon_lan() */
/***********************************************************************************************************************
* Function Name: callback_link_on
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_on(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
link_detect[channel] = ETHER_FLAG_ON_LINK_ON;
/* Please add necessary processing when becoming Link up. */
prvLinkStatusChange( 1 );
}
} /* End of function callback_link_on() */
/***********************************************************************************************************************
* Function Name: callback_link_off
* Description :
* Arguments : channel -
* Ethernet channel number
* Return Value : none
***********************************************************************************************************************/
static void callback_link_off(uint32_t channel)
{
if (ETHER_CHANNEL_MAX > channel)
{
link_detect[channel] = ETHER_FLAG_ON_LINK_OFF;
/* Please add necessary processing when becoming Link down. */
prvLinkStatusChange( 0 );
}
} /* End of function ether_cb_link_off() */
/* End of File */

View file

@ -1,118 +1,118 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Hardware includes. */
#include "hwEthernet.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
extern void vEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Initialise the MAC. */
vInitEmac();
while( lEMACWaitForLink() != pdPASS )
{
vTaskDelay( 20 );
}
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
xReturn = pdPASS;
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
/* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return pdTRUE;
}
/*-----------------------------------------------------------*/
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_UDP_IP.h"
#include "FreeRTOS_Sockets.h"
#include "NetworkBufferManagement.h"
/* Hardware includes. */
#include "hwEthernet.h"
/* Demo includes. */
#include "NetworkInterface.h"
#if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 1
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
/* When a packet is ready to be sent, if it cannot be sent immediately then the
task performing the transmit will block for niTX_BUFFER_FREE_WAIT
milliseconds. It will do this a maximum of niMAX_TX_ATTEMPTS before giving
up. */
#define niTX_BUFFER_FREE_WAIT ( ( TickType_t ) 2UL / portTICK_PERIOD_MS )
#define niMAX_TX_ATTEMPTS ( 5 )
/* The length of the queue used to send interrupt status words from the
interrupt handler to the deferred handler task. */
#define niINTERRUPT_QUEUE_LENGTH ( 10 )
/*-----------------------------------------------------------*/
/*
* A deferred interrupt handler task that processes
*/
extern void vEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* The queue used to communicate Ethernet events with the IP task. */
extern QueueHandle_t xNetworkEventQueue;
/* The semaphore used to wake the deferred interrupt handler task when an Rx
interrupt is received. */
SemaphoreHandle_t xEMACRxEventSemaphore = NULL;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
BaseType_t xStatus, xReturn;
extern uint8_t ucMACAddress[ 6 ];
/* Initialise the MAC. */
vInitEmac();
while( lEMACWaitForLink() != pdPASS )
{
vTaskDelay( 20 );
}
vSemaphoreCreateBinary( xEMACRxEventSemaphore );
configASSERT( xEMACRxEventSemaphore );
/* The handler task is created at the highest possible priority to
ensure the interrupt handler can return directly to it. */
xTaskCreate( vEMACHandlerTask, "EMAC", configMINIMAL_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL );
xReturn = pdPASS;
return xReturn;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer )
{
extern void vEMACCopyWrite( uint8_t * pucBuffer, uint16_t usLength );
vEMACCopyWrite( pxNetworkBuffer->pucBuffer, pxNetworkBuffer->xDataLength );
/* Finished with the network buffer. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
return pdTRUE;
}
/*-----------------------------------------------------------*/

View file

@ -1,60 +0,0 @@
This is a FreeeRTOS+TCP driver that works for both STM32F4xx and STM32F7xx parts.
The code of stm32fxx_hal_eth.c is based on both drivers as provided by ST.
These modules should be included:
NetworkInterface.c
stm32fxx_hal_eth.c
It is assumed that one of these words are defined:
STM32F7xx
STM32F407xx
STM32F417xx
STM32F427xx
STM32F437xx
STM32F429xx
STM32F439xx
The driver has been tested on both Eval and Discovery boards with both STM32F4 and STM32F7.
Recommened settings for STM32Fxx Network Interface:
// Defined in FreeRTOSIPConfig.h
#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1
#define ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM 1
#define ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM 1
#define ipconfigZERO_COPY_RX_DRIVER 1
#define ipconfigZERO_COPY_TX_DRIVER 1
#define ipconfigUSE_LINKED_RX_MESSAGES 1
// Defined in stm32f4xx_hal_conf.h
#define ETH_RXBUFNB 3 or 4
#define ETH_TXBUFNB 2 or 3
#define ETH_RX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 )
#define ETH_TX_BUF_SIZE ( ipconfigNETWORK_MTU + 36 )
The best size for 'ETH_RXBUFNB' and 'ETH_TXBUFNB' depends on the speed of the CPU. These macro's define the number of DMA buffers for reception and for transmission.
In general, if the CPU is very fast, you will need less buffers. You can obtain an estimate empirically.
The optimal value of 'ETH_RX_BUF_SIZE' and 'ETH_TX_BUF_SIZE' depends on the actual value of 'ipconfigNETWORK_MTU'.
When MTU is 1500, MTU+36 becomes a well-aligned buffer of 1536 bytes ( 0x600 ).
When MTU is 1200, MTU+48 will make 1248 ( 0x4E0 ), which is also well aligned.
Having well aligned buffers is important for CPU with memory cache. Often the caching system divides memory in blocks of 32 bytes. When two buffers share the same cache buffer, you are bound to see data errors.
Without memory caching, let the size be at least a multiple of 8 ( for DMA ), and make it at least "ipconfigNETWORK_MTU + 14".
The driver contains these files:
stm32fxx_hal_eth.c
stm32f2xx_hal_eth.h
stm32f4xx_hal_eth.h
stm32f7xx_hal_eth.h
stm32fxx_hal_eth.h
These files are copied from ST's HAL library. These work both for STM32F4 and STM32F7.
Please remove or rename these files from the HAL distribution that you are using.

View file

@ -1,6 +0,0 @@
/*
* The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
* a single module that works for both parts: "stm32fxx_hal_eth"
*/
#include "stm32fxx_hal_eth.h"

View file

@ -1,6 +0,0 @@
/*
* The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
* a single module that works for both parts: "stm32fxx_hal_eth"
*/
#include "stm32fxx_hal_eth.h"

View file

@ -1,6 +0,0 @@
/*
* The Ethernet header files for STM32F2, STM32F4 and STM32F7 have been merged to
* a single module that works for both parts: "stm32fxx_hal_eth"
*/
#include "stm32fxx_hal_eth.h"

View file

@ -1,175 +1,175 @@
#define xBUFFER_CACHE_SIZE 10
#define xMAX_FAULT_INJECTION_RATE 15
#define xMIN_FAULT_INJECTION_RATE 3
#define xNUM_FAULT_TYPES 1
static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
#define xFAULT_LOG_SIZE 2048
uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
uint32_t ulFaultLogIndex = 0;
static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
{
BaseType_t x, xReturn = pdFALSE;
for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
{
if( xNetworkBufferCache[ x ] == NULL )
{
xNetworkBufferCache[ x ] = pxNetworkBufferIn;
xReturn = pdTRUE;
break;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
{
BaseType_t x;
NetworkBufferDescriptor_t *pxReturn = NULL;
for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
{
if( xNetworkBufferCache[ x ] != NULL )
{
pxReturn = xNetworkBufferCache[ x ];
xNetworkBufferCache[ x ] = NULL;
break;
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
{
NetworkBufferDescriptor_t *pxReturn;
/* Obtain a new descriptor. */
pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
if( pxReturn != NULL )
{
/* Copy in the packet data. */
pxReturn->xDataLength = pxOriginalPacket->xDataLength;
memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
}
return pxReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
{
static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
uint32_t ulFault;
return pxNetworkBufferIn;
ulCallCount++;
if( ulCallCount > ulNextFaultCallCount )
{
xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );
ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
{
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
}
ulCallCount = 0;
xApplicationGetRandomNumber( &( ulFault ) );
ulFault = ulFault % xNUM_FAULT_TYPES;
if( ulFaultLogIndex < xFAULT_LOG_SIZE )
{
ulInjectedFault[ ulFaultLogIndex ] = ulFault;
ulFaultLogIndex++;
}
switch( ulFault )
{
case 0:
/* Just drop the packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
pxReturn = NULL;
break;
case 1:
/* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{
/* The packet may get sent later, it is not being sent
now. */
pxReturn = NULL;
}
break;
case 2:
/* Send a cached packet. */
pxReturn = prvGetCachedPacket();
if( pxReturn != NULL )
{
/* A cached packet was obtained so drop the original
packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
else
{
/* Could not obtain a packet from the cache so just return
the packet that was passed in. */
pxReturn = pxNetworkBufferIn;
}
break;
case 4:
/* Send a duplicate of the packet right away. */
pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
/* Send the original packet to the stack. */
xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
break;
case 5:
/* Send both a cached packet and the current packet. */
xRxEvent.pvData = ( void * ) prvGetCachedPacket();
if( xRxEvent.pvData != NULL )
{
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
}
break;
case 6:
case 7:
case 8:
/* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{
/* The packet may get sent later, it is not being sent
now. */
pxReturn = NULL;
}
break;
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/
#define xBUFFER_CACHE_SIZE 10
#define xMAX_FAULT_INJECTION_RATE 15
#define xMIN_FAULT_INJECTION_RATE 3
#define xNUM_FAULT_TYPES 1
static NetworkBufferDescriptor_t *xNetworkBufferCache[ xBUFFER_CACHE_SIZE ] = { 0 };
#define xFAULT_LOG_SIZE 2048
uint32_t ulInjectedFault[ xFAULT_LOG_SIZE ];
uint32_t ulFaultLogIndex = 0;
static BaseType_t prvCachePacket( NetworkBufferDescriptor_t *pxNetworkBufferIn )
{
BaseType_t x, xReturn = pdFALSE;
for( x = 0; x < xBUFFER_CACHE_SIZE; x++ )
{
if( xNetworkBufferCache[ x ] == NULL )
{
xNetworkBufferCache[ x ] = pxNetworkBufferIn;
xReturn = pdTRUE;
break;
}
}
return xReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvGetCachedPacket( void )
{
BaseType_t x;
NetworkBufferDescriptor_t *pxReturn = NULL;
for( x = ( xBUFFER_CACHE_SIZE - 1 ); x >= 0; x-- )
{
if( xNetworkBufferCache[ x ] != NULL )
{
pxReturn = xNetworkBufferCache[ x ];
xNetworkBufferCache[ x ] = NULL;
break;
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvDuplicatePacket( NetworkBufferDescriptor_t * pxOriginalPacket, const uint8_t *pucPacketData )
{
NetworkBufferDescriptor_t *pxReturn;
/* Obtain a new descriptor. */
pxReturn = pxGetNetworkBufferWithDescriptor( pxOriginalPacket->xDataLength, 0 );
if( pxReturn != NULL )
{
/* Copy in the packet data. */
pxReturn->xDataLength = pxOriginalPacket->xDataLength;
memcpy( pxReturn->pucEthernetBuffer, pucPacketData, pxOriginalPacket->xDataLength );
}
return pxReturn;
}
/*-----------------------------------------------------------*/
static NetworkBufferDescriptor_t *prvRxFaultInjection( NetworkBufferDescriptor_t *pxNetworkBufferIn, const uint8_t *pucPacketData )
{
static uint32_t ulCallCount = 0, ulNextFaultCallCount = 0;
NetworkBufferDescriptor_t *pxReturn = pxNetworkBufferIn;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
uint32_t ulFault;
return pxNetworkBufferIn;
ulCallCount++;
if( ulCallCount > ulNextFaultCallCount )
{
xApplicationGetRandomNumber( &( ulNextFaultCallCount ) );
ulNextFaultCallCount = ulNextFaultCallCount % xMAX_FAULT_INJECTION_RATE;
if( ulNextFaultCallCount < xMIN_FAULT_INJECTION_RATE )
{
ulNextFaultCallCount = xMIN_FAULT_INJECTION_RATE;
}
ulCallCount = 0;
xApplicationGetRandomNumber( &( ulFault ) );
ulFault = ulFault % xNUM_FAULT_TYPES;
if( ulFaultLogIndex < xFAULT_LOG_SIZE )
{
ulInjectedFault[ ulFaultLogIndex ] = ulFault;
ulFaultLogIndex++;
}
switch( ulFault )
{
case 0:
/* Just drop the packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
pxReturn = NULL;
break;
case 1:
/* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{
/* The packet may get sent later, it is not being sent
now. */
pxReturn = NULL;
}
break;
case 2:
/* Send a cached packet. */
pxReturn = prvGetCachedPacket();
if( pxReturn != NULL )
{
/* A cached packet was obtained so drop the original
packet. */
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
else
{
/* Could not obtain a packet from the cache so just return
the packet that was passed in. */
pxReturn = pxNetworkBufferIn;
}
break;
case 4:
/* Send a duplicate of the packet right away. */
pxReturn = prvDuplicatePacket( pxNetworkBufferIn, pucPacketData );
/* Send the original packet to the stack. */
xRxEvent.pvData = ( void * ) pxNetworkBufferIn;
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
break;
case 5:
/* Send both a cached packet and the current packet. */
xRxEvent.pvData = ( void * ) prvGetCachedPacket();
if( xRxEvent.pvData != NULL )
{
if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0 ) == pdFAIL )
{
vReleaseNetworkBufferAndDescriptor( pxNetworkBufferIn );
}
}
break;
case 6:
case 7:
case 8:
/* Store the packet in the cache for later. */
if( prvCachePacket( pxNetworkBufferIn ) == pdTRUE )
{
/* The packet may get sent later, it is not being sent
now. */
pxReturn = NULL;
}
break;
}
}
return pxReturn;
}
/*-----------------------------------------------------------*/

View file

@ -1,398 +1,398 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* Xilinx library files. */
#include <xemacps.h>
#include "Zynq/x_topology.h"
#include "Zynq/x_emacpsif.h"
#include "Zynq/x_emacpsif_hw.h"
/* Provided memory configured as uncached. */
#include "uncached_memory.h"
#ifndef BMSR_LINK_STATUS
#define BMSR_LINK_STATUS 0x0004UL
#endif
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
receiving packets. */
#define PHY_LS_HIGH_CHECK_TIME_MS 15000
#endif
#ifndef PHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still low every second. */
#define PHY_LS_LOW_CHECK_TIME_MS 1000
#endif
/* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536
/* Naming and numbering of PHY registers. */
#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
#ifndef iptraceEMAC_TASK_STARTING
#define iptraceEMAC_TASK_STARTING() do { } while( 0 )
#endif
/* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
/*-----------------------------------------------------------*/
/*
* Look for the link to be up every few milliseconds until either xMaxTime time
* has passed or a link is found.
*/
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
/*
* A deferred interrupt handler for all MAC/DMA interrupt sources.
*/
static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* EMAC data/descriptions. */
static xemacpsif_s xEMACpsif;
struct xtopology_t xXTopology =
{
.emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
.emac_type = xemac_type_emacps,
.intc_baseaddr = 0x0,
.intc_emac_intr = 0x0,
.scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
.scugic_emac_intr = 0x36,
};
XEmacPs_Config mac_config =
{
.DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
.BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
};
extern int phy_detected;
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
static uint32_t ulPHYLinkStatus = 0;
#if( ipconfigUSE_LLMNR == 1 )
static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
#endif
/* ucMACAddress as it appears in main.c */
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;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
uint32_t ulLinkSpeed, ulDMAReg;
BaseType_t xStatus, xLinkStatus;
XEmacPs *pxEMAC_PS;
const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
/* Guard against the init function being called more than once. */
if( xEMACTaskHandle == NULL )
{
pxEMAC_PS = &( xEMACpsif.emacps );
memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
if( xStatus != XST_SUCCESS )
{
FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
}
/* Initialize the mac and set the MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
#if( ipconfigUSE_LLMNR == 1 )
{
/* Also add LLMNR multicast MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
}
#endif /* ipconfigUSE_LLMNR == 1 */
XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
ulLinkSpeed = Phy_Setup( pxEMAC_PS );
XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
/* Setting the operating speed of the MAC needs a delay. */
vTaskDelay( pdMS_TO_TICKS( 25UL ) );
ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
/* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
packets from the receiver packet buffer memory when no AHB resource is available. */
XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
setup_isr( &xEMACpsif );
init_dma( &xEMACpsif );
start_emacps( &xEMACpsif );
prvGMACWaitLS( xWaitLinkDelay );
/* The deferred interrupt handler task is created at the highest
possible priority to ensure the interrupt handler can return directly
to it. The task's handle is stored in xEMACTaskHandle so interrupts can
notify the task when there is something to process. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
}
else
{
/* Initialisation was already performed, just wait for the link. */
prvGMACWaitLS( xWaitRelinkDelay );
}
/* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
DHCP process and all other communication will fail. */
xLinkStatus = xGetPhyLinkStatus();
return ( xLinkStatus != pdFALSE );
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
{
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
}
else if( bReleaseAfterSend != pdFALSE )
{
/* No link. */
vReleaseNetworkBufferAndDescriptor( pxBuffer );
}
return pdTRUE;
}
/*-----------------------------------------------------------*/
static inline unsigned long ulReadMDIO( unsigned ulRegister )
{
uint16_t usValue;
XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
return usValue;
}
/*-----------------------------------------------------------*/
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
{
TickType_t xStartTime, xEndTime;
const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
BaseType_t xReturn;
xStartTime = xTaskGetTickCount();
for( ;; )
{
xEndTime = xTaskGetTickCount();
if( xEndTime - xStartTime > xMaxTime )
{
xReturn = pdFALSE;
break;
}
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
xReturn = pdTRUE;
break;
}
vTaskDelay( xShortDelay );
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
}
}
/*-----------------------------------------------------------*/
BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters )
{
TimeOut_t xPhyTime;
TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount;
BaseType_t xResult = 0;
uint32_t xStatus;
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* A possibility to set some additional task properties like calling
portTASK_USES_FLOATING_POINT() */
iptraceEMAC_TASK_STARTING();
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
for( ;; )
{
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( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
static UBaseType_t uxLastMinQueueSpace = 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 */
if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
{
/* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
}
if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
xResult = emacps_check_rx( &xEMACpsif );
}
if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
emacps_check_tx( &xEMACpsif );
}
if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
emacps_check_errors( &xEMACpsif );
}
if( xResult > 0 )
{
/* A packet was received. No need to check for the PHY status now,
but set a timer to check it later on. */
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
xResult = 0;
}
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
{
xStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
{
ulPHYLinkStatus = xStatus;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
}
vTaskSetTimeOutState( &xPhyTime );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
}
}
}
}
/*-----------------------------------------------------------*/
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2017 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
/* Xilinx library files. */
#include <xemacps.h>
#include "Zynq/x_topology.h"
#include "Zynq/x_emacpsif.h"
#include "Zynq/x_emacpsif_hw.h"
/* Provided memory configured as uncached. */
#include "uncached_memory.h"
#ifndef BMSR_LINK_STATUS
#define BMSR_LINK_STATUS 0x0004UL
#endif
#ifndef PHY_LS_HIGH_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still high after 15 seconds of not
receiving packets. */
#define PHY_LS_HIGH_CHECK_TIME_MS 15000
#endif
#ifndef PHY_LS_LOW_CHECK_TIME_MS
/* Check if the LinkSStatus in the PHY is still low every second. */
#define PHY_LS_LOW_CHECK_TIME_MS 1000
#endif
/* The size of each buffer when BufferAllocation_1 is used:
http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html */
#define niBUFFER_1_PACKET_SIZE 1536
/* Naming and numbering of PHY registers. */
#define PHY_REG_01_BMSR 0x01 /* Basic mode status register */
#ifndef iptraceEMAC_TASK_STARTING
#define iptraceEMAC_TASK_STARTING() do { } while( 0 )
#endif
/* Default the size of the stack used by the EMAC deferred handler task to twice
the size of the stack used by the idle task - but allow this to be overridden in
FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#ifndef configEMAC_TASK_STACK_SIZE
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
/*-----------------------------------------------------------*/
/*
* Look for the link to be up every few milliseconds until either xMaxTime time
* has passed or a link is found.
*/
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime );
/*
* A deferred interrupt handler for all MAC/DMA interrupt sources.
*/
static void prvEMACHandlerTask( void *pvParameters );
/*-----------------------------------------------------------*/
/* EMAC data/descriptions. */
static xemacpsif_s xEMACpsif;
struct xtopology_t xXTopology =
{
.emac_baseaddr = XPAR_PS7_ETHERNET_0_BASEADDR,
.emac_type = xemac_type_emacps,
.intc_baseaddr = 0x0,
.intc_emac_intr = 0x0,
.scugic_baseaddr = XPAR_PS7_SCUGIC_0_BASEADDR,
.scugic_emac_intr = 0x36,
};
XEmacPs_Config mac_config =
{
.DeviceId = XPAR_PS7_ETHERNET_0_DEVICE_ID, /**< Unique ID of device */
.BaseAddress = XPAR_PS7_ETHERNET_0_BASEADDR /**< Physical base address of IPIF registers */
};
extern int phy_detected;
/* A copy of PHY register 1: 'PHY_REG_01_BMSR' */
static uint32_t ulPHYLinkStatus = 0;
#if( ipconfigUSE_LLMNR == 1 )
static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC };
#endif
/* ucMACAddress as it appears in main.c */
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;
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
{
uint32_t ulLinkSpeed, ulDMAReg;
BaseType_t xStatus, xLinkStatus;
XEmacPs *pxEMAC_PS;
const TickType_t xWaitLinkDelay = pdMS_TO_TICKS( 7000UL ), xWaitRelinkDelay = pdMS_TO_TICKS( 1000UL );
/* Guard against the init function being called more than once. */
if( xEMACTaskHandle == NULL )
{
pxEMAC_PS = &( xEMACpsif.emacps );
memset( &xEMACpsif, '\0', sizeof( xEMACpsif ) );
xStatus = XEmacPs_CfgInitialize( pxEMAC_PS, &mac_config, mac_config.BaseAddress);
if( xStatus != XST_SUCCESS )
{
FreeRTOS_printf( ( "xEMACInit: EmacPs Configuration Failed....\n" ) );
}
/* Initialize the mac and set the MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * ) ucMACAddress, 1 );
#if( ipconfigUSE_LLMNR == 1 )
{
/* Also add LLMNR multicast MAC address. */
XEmacPs_SetMacAddress( pxEMAC_PS, ( void * )xLLMNR_MACAddress, 2 );
}
#endif /* ipconfigUSE_LLMNR == 1 */
XEmacPs_SetMdioDivisor( pxEMAC_PS, MDC_DIV_224 );
ulLinkSpeed = Phy_Setup( pxEMAC_PS );
XEmacPs_SetOperatingSpeed( pxEMAC_PS, ulLinkSpeed);
/* Setting the operating speed of the MAC needs a delay. */
vTaskDelay( pdMS_TO_TICKS( 25UL ) );
ulDMAReg = XEmacPs_ReadReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET);
/* DISC_WHEN_NO_AHB: when set, the GEM DMA will automatically discard receive
packets from the receiver packet buffer memory when no AHB resource is available. */
XEmacPs_WriteReg( pxEMAC_PS->Config.BaseAddress, XEMACPS_DMACR_OFFSET,
ulDMAReg | XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK);
setup_isr( &xEMACpsif );
init_dma( &xEMACpsif );
start_emacps( &xEMACpsif );
prvGMACWaitLS( xWaitLinkDelay );
/* The deferred interrupt handler task is created at the highest
possible priority to ensure the interrupt handler can return directly
to it. The task's handle is stored in xEMACTaskHandle so interrupts can
notify the task when there is something to process. */
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );
}
else
{
/* Initialisation was already performed, just wait for the link. */
prvGMACWaitLS( xWaitRelinkDelay );
}
/* Only return pdTRUE when the Link Status of the PHY is high, otherwise the
DHCP process and all other communication will fail. */
xLinkStatus = xGetPhyLinkStatus();
return ( xLinkStatus != pdFALSE );
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxBuffer, BaseType_t bReleaseAfterSend )
{
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
iptraceNETWORK_INTERFACE_TRANSMIT();
emacps_send_message( &xEMACpsif, pxBuffer, bReleaseAfterSend );
}
else if( bReleaseAfterSend != pdFALSE )
{
/* No link. */
vReleaseNetworkBufferAndDescriptor( pxBuffer );
}
return pdTRUE;
}
/*-----------------------------------------------------------*/
static inline unsigned long ulReadMDIO( unsigned ulRegister )
{
uint16_t usValue;
XEmacPs_PhyRead( &( xEMACpsif.emacps ), phy_detected, ulRegister, &usValue );
return usValue;
}
/*-----------------------------------------------------------*/
static BaseType_t prvGMACWaitLS( TickType_t xMaxTime )
{
TickType_t xStartTime, xEndTime;
const TickType_t xShortDelay = pdMS_TO_TICKS( 20UL );
BaseType_t xReturn;
xStartTime = xTaskGetTickCount();
for( ;; )
{
xEndTime = xTaskGetTickCount();
if( xEndTime - xStartTime > xMaxTime )
{
xReturn = pdFALSE;
break;
}
ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
xReturn = pdTRUE;
break;
}
vTaskDelay( xShortDelay );
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );
uint8_t *ucRAMBuffer = ucNetworkPackets;
uint32_t ul;
for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ )
{
pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING;
*( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) );
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;
}
}
/*-----------------------------------------------------------*/
BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) == 0 )
{
xReturn = pdFALSE;
}
else
{
xReturn = pdTRUE;
}
return xReturn;
}
/*-----------------------------------------------------------*/
static void prvEMACHandlerTask( void *pvParameters )
{
TimeOut_t xPhyTime;
TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0;
UBaseType_t uxCurrentCount;
BaseType_t xResult = 0;
uint32_t xStatus;
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
/* A possibility to set some additional task properties like calling
portTASK_USES_FLOATING_POINT() */
iptraceEMAC_TASK_STARTING();
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
for( ;; )
{
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( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
static UBaseType_t uxLastMinQueueSpace = 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 */
if( ( xEMACpsif.isr_events & EMAC_IF_ALL_EVENT ) == 0 )
{
/* No events to process now, wait for the next. */
ulTaskNotifyTake( pdFALSE, ulMaxBlockTime );
}
if( ( xEMACpsif.isr_events & EMAC_IF_RX_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_RX_EVENT;
xResult = emacps_check_rx( &xEMACpsif );
}
if( ( xEMACpsif.isr_events & EMAC_IF_TX_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_TX_EVENT;
emacps_check_tx( &xEMACpsif );
}
if( ( xEMACpsif.isr_events & EMAC_IF_ERR_EVENT ) != 0 )
{
xEMACpsif.isr_events &= ~EMAC_IF_ERR_EVENT;
emacps_check_errors( &xEMACpsif );
}
if( xResult > 0 )
{
/* A packet was received. No need to check for the PHY status now,
but set a timer to check it later on. */
vTaskSetTimeOutState( &xPhyTime );
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
xResult = 0;
}
else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE )
{
xStatus = ulReadMDIO( PHY_REG_01_BMSR );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
{
ulPHYLinkStatus = xStatus;
FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
}
vTaskSetTimeOutState( &xPhyTime );
if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS );
}
else
{
xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
}
}
}
}
/*-----------------------------------------------------------*/

View file

@ -1,25 +1,25 @@
NetworkInterface for Xilinx' Zynq
Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
And include the following source files from the Xilinx library:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c
E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c
The following source files are NOT used for the FreeRTOS+TCP interface:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c
NetworkInterface for Xilinx' Zynq
Please include the following source files:
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/NetworkInterface.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_dma.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_physpeed.c
$(PLUS_TCP_PATH)/portable/NetworkInterface/Zynq/x_emacpsif_hw.c
And include the following source files from the Xilinx library:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_control.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_g.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_intr.c
E.g. ps7_cortexa9_0/libsrc/emacps_v2_0/src/xemacps_intr.c
The following source files are NOT used for the FreeRTOS+TCP interface:
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_bdring.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_hw.c
$(CPU_PATH)/$(PROCESSOR)/libsrc/emacps_v2_0/src/xemacps_sinit.c

View file

@ -1,132 +0,0 @@
/*
* uncached_memory.c
*
* This module will declare 1 MB of memory and switch off the caching for it.
*
* pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
* rounded up to a multiple of 4 KB
*
* ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
* within the range of the 1 MB non-cached memory.
*
*/
/*
* After "_end", 1 MB of uncached memory will be allocated for DMA transfers.
* Both the DMA descriptors as well as all EMAC TX-buffers will be allocated in
* uncached memory.
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "Zynq/x_emacpsif.h"
#include "Zynq/x_topology.h"
#include "xstatus.h"
#include "xparameters.h"
#include "xparameters_ps.h"
#include "xil_exception.h"
#include "xil_mmu.h"
#include "uncached_memory.h"
#define UNCACHED_MEMORY_SIZE 0x100000ul
#define DDR_MEMORY_END (XPAR_PS7_DDR_0_S_AXI_HIGHADDR+1)
static void vInitialiseUncachedMemory( void );
static uint8_t *pucHeadOfMemory;
static uint32_t ulMemorySize;
static uint8_t *pucStartOfMemory = NULL;
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer )
{
uint8_t ucReturn;
if( ( pucStartOfMemory != NULL ) &&
( pucBuffer >= pucStartOfMemory ) &&
( pucBuffer < ( pucStartOfMemory + UNCACHED_MEMORY_SIZE ) ) )
{
ucReturn = pdFALSE;
}
else
{
ucReturn = pdTRUE;
}
return ucReturn;
}
uint8_t *pucGetUncachedMemory( uint32_t ulSize )
{
uint8_t *pucReturn;
if( pucStartOfMemory == NULL )
{
vInitialiseUncachedMemory( );
}
if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) )
{
pucReturn = NULL;
}
else
{
uint32_t ulSkipSize;
pucReturn = pucHeadOfMemory;
ulSkipSize = ( ulSize + 0x1000ul ) & ~0xffful;
pucHeadOfMemory += ulSkipSize;
ulMemorySize -= ulSkipSize;
}
return pucReturn;
}
extern u8 _end;
static void vInitialiseUncachedMemory( )
{
/* At the end of program's space... */
pucStartOfMemory = (uint8_t *) &_end;
/*
* Align the start address to 1 MB boundary.
*/
pucStartOfMemory = (uint8_t *)( ( ( uint32_t )pucStartOfMemory + UNCACHED_MEMORY_SIZE ) & ( ~( UNCACHED_MEMORY_SIZE - 1 ) ) );
if( ( ( u32 )pucStartOfMemory ) + UNCACHED_MEMORY_SIZE > DDR_MEMORY_END )
{
// vLoggingPrintf("vInitialiseUncachedMemory: Can not allocate uncached memory\n" );
}
else
{
/*
* Some objects want to be stored in uncached memory. Hence the 1 MB
* address range that starts after "_end" is made uncached
* by setting appropriate attributes in the translation table.
*/
/* FIXME claudio rossi. Modified to prevent data abort exception (misaligned access)
* when application is compiled with -O1 or more optimization flag.
*/
/* Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0xc02 ); // addr, attr */
Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0x1c02 ); // addr, attr
/* For experiments in the SDIO driver, make the remaining uncached memory public */
pucHeadOfMemory = pucStartOfMemory;
ulMemorySize = UNCACHED_MEMORY_SIZE;
memset( pucStartOfMemory, '\0', UNCACHED_MEMORY_SIZE );
}
}

View file

@ -1,23 +0,0 @@
/*
* uncached_memory.h
*
* This module will declare 1 MB of memory and switch off the caching for it.
*
* pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
* rounded up to a multiple of 4 KB
*
* ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
* within the range of the 1 MB non-cached memory.
*
*/
#ifndef UNCACHEMEMORY_H
#define UNCACHEMEMORY_H
uint8_t *pucGetUncachedMemory( uint32_t ulSize );
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer );
#endif /* UNCACHEMEMORY_H */

View file

@ -1,144 +1,144 @@
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __NETIF_XEMACPSIF_H__
#define __NETIF_XEMACPSIF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "xstatus.h"
#include "sleep.h"
#include "xparameters.h"
#include "xparameters_ps.h" /* defines XPAR values */
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xpseudo_asm.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xuartps.h"
#include "xscugic.h"
#include "xemacps.h" /* defines XEmacPs API */
//#include "netif/xpqueue.h"
//#include "xlwipconfig.h"
void xemacpsif_setmac(uint32_t index, uint8_t *addr);
uint8_t* xemacpsif_getmac(uint32_t index);
//int xemacpsif_init(struct netif *netif);
//int xemacpsif_input(struct netif *netif);
#ifdef NOTNOW_BHILL
unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
#endif
/* xaxiemacif_hw.c */
void xemacps_error_handler(XEmacPs * Temac);
struct xBD_TYPE {
uint32_t address;
uint32_t flags;
};
/*
* Missing declaration in 'src/xemacps_hw.h' :
* When set, the GEM DMA will automatically
* discard receive packets from the receiver packet
* buffer memory when no AHB resource is
* available.
* When low, then received packets will remain to be
* stored in the SRAM based packet buffer until
* AHB buffer resource next becomes available.
*/
#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
#define EMAC_IF_RX_EVENT 1
#define EMAC_IF_TX_EVENT 2
#define EMAC_IF_ERR_EVENT 4
#define EMAC_IF_ALL_EVENT 7
/* structure within each netif, encapsulating all information required for
* using a particular temac instance
*/
typedef struct {
XEmacPs emacps;
/* pointers to memory holding buffer descriptors (used only with SDMA) */
struct xBD_TYPE *rxSegments;
struct xBD_TYPE *txSegments;
unsigned char *tx_space;
unsigned uTxUnitSize;
char *remain_mem;
unsigned remain_siz;
volatile int rxHead, rxTail;
volatile int txHead, txTail;
volatile int txBusy;
volatile uint32_t isr_events;
unsigned int last_rx_frms_cntr;
} xemacpsif_s;
//extern xemacpsif_s xemacpsif;
int is_tx_space_available(xemacpsif_s *emac);
/* xaxiemacif_dma.c */
struct xNETWORK_BUFFER;
int emacps_check_rx( xemacpsif_s *xemacpsif );
void emacps_check_tx( xemacpsif_s *xemacpsif );
int emacps_check_errors( xemacpsif_s *xemacps );
void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
extern unsigned Phy_Setup( XEmacPs *xemacpsp );
extern void setup_isr( xemacpsif_s *xemacpsif );
extern XStatus init_dma( xemacpsif_s *xemacpsif );
extern void start_emacps( xemacpsif_s *xemacpsif );
void EmacEnableIntr(void);
void EmacDisableIntr(void);
XStatus init_axi_dma(xemacpsif_s *xemacpsif);
void process_sent_bds( xemacpsif_s *xemacpsif );
void emacps_send_handler(void *arg);
void emacps_recv_handler(void *arg);
void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
void HandleTxErrors(xemacpsif_s *xemacpsif);
XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
void clean_dma_txdescs(xemacpsif_s *xemacpsif);
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
#ifdef __cplusplus
}
#endif
#endif /* __NETIF_XAXIEMACIF_H__ */
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __NETIF_XEMACPSIF_H__
#define __NETIF_XEMACPSIF_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "xstatus.h"
#include "sleep.h"
#include "xparameters.h"
#include "xparameters_ps.h" /* defines XPAR values */
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
#include "xil_exception.h"
#include "xpseudo_asm.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xuartps.h"
#include "xscugic.h"
#include "xemacps.h" /* defines XEmacPs API */
//#include "netif/xpqueue.h"
//#include "xlwipconfig.h"
void xemacpsif_setmac(uint32_t index, uint8_t *addr);
uint8_t* xemacpsif_getmac(uint32_t index);
//int xemacpsif_init(struct netif *netif);
//int xemacpsif_input(struct netif *netif);
#ifdef NOTNOW_BHILL
unsigned get_IEEE_phy_speed(XLlTemac *xlltemacp);
#endif
/* xaxiemacif_hw.c */
void xemacps_error_handler(XEmacPs * Temac);
struct xBD_TYPE {
uint32_t address;
uint32_t flags;
};
/*
* Missing declaration in 'src/xemacps_hw.h' :
* When set, the GEM DMA will automatically
* discard receive packets from the receiver packet
* buffer memory when no AHB resource is
* available.
* When low, then received packets will remain to be
* stored in the SRAM based packet buffer until
* AHB buffer resource next becomes available.
*/
#define XEMACPS_DMACR_DISC_WHEN_NO_AHB_MASK 0x01000000
#define EMAC_IF_RX_EVENT 1
#define EMAC_IF_TX_EVENT 2
#define EMAC_IF_ERR_EVENT 4
#define EMAC_IF_ALL_EVENT 7
/* structure within each netif, encapsulating all information required for
* using a particular temac instance
*/
typedef struct {
XEmacPs emacps;
/* pointers to memory holding buffer descriptors (used only with SDMA) */
struct xBD_TYPE *rxSegments;
struct xBD_TYPE *txSegments;
unsigned char *tx_space;
unsigned uTxUnitSize;
char *remain_mem;
unsigned remain_siz;
volatile int rxHead, rxTail;
volatile int txHead, txTail;
volatile int txBusy;
volatile uint32_t isr_events;
unsigned int last_rx_frms_cntr;
} xemacpsif_s;
//extern xemacpsif_s xemacpsif;
int is_tx_space_available(xemacpsif_s *emac);
/* xaxiemacif_dma.c */
struct xNETWORK_BUFFER;
int emacps_check_rx( xemacpsif_s *xemacpsif );
void emacps_check_tx( xemacpsif_s *xemacpsif );
int emacps_check_errors( xemacpsif_s *xemacps );
void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount );
extern XStatus emacps_send_message(xemacpsif_s *xemacpsif, struct xNETWORK_BUFFER *pxBuffer, int iReleaseAfterSend );
extern unsigned Phy_Setup( XEmacPs *xemacpsp );
extern void setup_isr( xemacpsif_s *xemacpsif );
extern XStatus init_dma( xemacpsif_s *xemacpsif );
extern void start_emacps( xemacpsif_s *xemacpsif );
void EmacEnableIntr(void);
void EmacDisableIntr(void);
XStatus init_axi_dma(xemacpsif_s *xemacpsif);
void process_sent_bds( xemacpsif_s *xemacpsif );
void emacps_send_handler(void *arg);
void emacps_recv_handler(void *arg);
void emacps_error_handler(void *arg,u8 Direction, u32 ErrorWord);
void HandleTxErrors(xemacpsif_s *xemacpsif);
XEmacPs_Config *xemacps_lookup_config(unsigned mac_base);
void clean_dma_txdescs(xemacpsif_s *xemacpsif);
void resetrx_on_no_rxdata(xemacpsif_s *xemacpsif);
#ifdef __cplusplus
}
#endif
#endif /* __NETIF_XAXIEMACIF_H__ */

View file

@ -1,243 +1,243 @@
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "Zynq/x_emacpsif.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
///* FreeRTOS+TCP includes. */
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
extern TaskHandle_t xEMACTaskHandle;
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
*** to run it on a PEEP board
***/
unsigned int link_speed = 100;
void setup_isr( xemacpsif_s *xemacpsif )
{
/*
* Setup callbacks
*/
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
(void *) emacps_send_handler,
(void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
(void *) emacps_recv_handler,
(void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
(void *) emacps_error_handler,
(void *) xemacpsif);
}
void start_emacps (xemacpsif_s *xemacps)
{
/* start the temac */
XEmacPs_Start(&xemacps->emacps);
}
extern struct xtopology_t xXTopology;
volatile int error_msg_count = 0;
volatile const char *last_err_msg = "";
struct xERROR_MSG {
void *arg;
u8 Direction;
u32 ErrorWord;
};
static struct xERROR_MSG xErrorList[ 8 ];
static BaseType_t xErrorHead, xErrorTail;
void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xemacpsif_s *xemacpsif;
BaseType_t xNextHead = xErrorHead;
xemacpsif = (xemacpsif_s *)(arg);
if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
{
if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
xNextHead = 0;
if( xNextHead != xErrorTail )
{
xErrorList[ xErrorHead ].arg = arg;
xErrorList[ xErrorHead ].Direction = Direction;
xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
xErrorHead = xNextHead;
xemacpsif = (xemacpsif_s *)(arg);
xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
}
if( xEMACTaskHandle != NULL )
{
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
}
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
int emacps_check_errors( xemacpsif_s *xemacps )
{
int xResult;
( void ) xemacps;
if( xErrorHead == xErrorTail )
{
xResult = 0;
}
else
{
xResult = 1;
emacps_handle_error(
xErrorList[ xErrorTail ].arg,
xErrorList[ xErrorTail ].Direction,
xErrorList[ xErrorTail ].ErrorWord );
}
return xResult;
}
BaseType_t xNetworkInterfaceInitialise( void );
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
{
xemacpsif_s *xemacpsif;
struct xtopology_t *xtopologyp;
XEmacPs *xemacps;
xemacpsif = (xemacpsif_s *)(arg);
xtopologyp = &xXTopology;
xemacps = &xemacpsif->emacps;
/* Do not appear to be used. */
( void ) xemacps;
( void ) xtopologyp;
last_err_msg = NULL;
if( ErrorWord != 0 )
{
switch (Direction) {
case XEMACPS_RECV:
if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
{
last_err_msg = "Receive DMA error";
xNetworkInterfaceInitialise( );
}
if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
{
last_err_msg = "Receive over run";
emacps_recv_handler(arg);
}
if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
{
last_err_msg = "Receive buffer not available";
emacps_recv_handler(arg);
}
break;
case XEMACPS_SEND:
if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
{
last_err_msg = "Transmit DMA error";
xNetworkInterfaceInitialise( );
}
if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
{
last_err_msg = "Transmit under run";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
{
last_err_msg = "Transmit buffer exhausted";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
{
last_err_msg = "Transmit retry excessed limits";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
{
last_err_msg = "Transmit collision";
emacps_check_tx( xemacpsif );
}
break;
}
}
// Break on this statement and inspect error_msg if you like
if( last_err_msg != NULL )
{
error_msg_count++;
FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
}
}
extern XEmacPs_Config mac_config;
void HandleTxErrors(xemacpsif_s *xemacpsif)
{
u32 netctrlreg;
//taskENTER_CRITICAL()
{
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg);
clean_dma_txdescs( xemacpsif );
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg);
}
//taskEXIT_CRITICAL( );
}
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "Zynq/x_emacpsif.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
///* FreeRTOS+TCP includes. */
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
extern TaskHandle_t xEMACTaskHandle;
/*** IMPORTANT: Define PEEP in xemacpsif.h and sys_arch_raw.c
*** to run it on a PEEP board
***/
unsigned int link_speed = 100;
void setup_isr( xemacpsif_s *xemacpsif )
{
/*
* Setup callbacks
*/
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMASEND,
(void *) emacps_send_handler,
(void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_DMARECV,
(void *) emacps_recv_handler,
(void *) xemacpsif);
XEmacPs_SetHandler(&xemacpsif->emacps, XEMACPS_HANDLER_ERROR,
(void *) emacps_error_handler,
(void *) xemacpsif);
}
void start_emacps (xemacpsif_s *xemacps)
{
/* start the temac */
XEmacPs_Start(&xemacps->emacps);
}
extern struct xtopology_t xXTopology;
volatile int error_msg_count = 0;
volatile const char *last_err_msg = "";
struct xERROR_MSG {
void *arg;
u8 Direction;
u32 ErrorWord;
};
static struct xERROR_MSG xErrorList[ 8 ];
static BaseType_t xErrorHead, xErrorTail;
void emacps_error_handler(void *arg, u8 Direction, u32 ErrorWord)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xemacpsif_s *xemacpsif;
BaseType_t xNextHead = xErrorHead;
xemacpsif = (xemacpsif_s *)(arg);
if( ( Direction != XEMACPS_SEND ) || (ErrorWord != XEMACPS_TXSR_USEDREAD_MASK ) )
{
if( ++xNextHead == ( sizeof( xErrorList ) / sizeof( xErrorList[ 0 ] ) ) )
xNextHead = 0;
if( xNextHead != xErrorTail )
{
xErrorList[ xErrorHead ].arg = arg;
xErrorList[ xErrorHead ].Direction = Direction;
xErrorList[ xErrorHead ].ErrorWord = ErrorWord;
xErrorHead = xNextHead;
xemacpsif = (xemacpsif_s *)(arg);
xemacpsif->isr_events |= EMAC_IF_ERR_EVENT;
}
if( xEMACTaskHandle != NULL )
{
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
}
}
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord);
int emacps_check_errors( xemacpsif_s *xemacps )
{
int xResult;
( void ) xemacps;
if( xErrorHead == xErrorTail )
{
xResult = 0;
}
else
{
xResult = 1;
emacps_handle_error(
xErrorList[ xErrorTail ].arg,
xErrorList[ xErrorTail ].Direction,
xErrorList[ xErrorTail ].ErrorWord );
}
return xResult;
}
BaseType_t xNetworkInterfaceInitialise( void );
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord)
{
xemacpsif_s *xemacpsif;
struct xtopology_t *xtopologyp;
XEmacPs *xemacps;
xemacpsif = (xemacpsif_s *)(arg);
xtopologyp = &xXTopology;
xemacps = &xemacpsif->emacps;
/* Do not appear to be used. */
( void ) xemacps;
( void ) xtopologyp;
last_err_msg = NULL;
if( ErrorWord != 0 )
{
switch (Direction) {
case XEMACPS_RECV:
if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 )
{
last_err_msg = "Receive DMA error";
xNetworkInterfaceInitialise( );
}
if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 )
{
last_err_msg = "Receive over run";
emacps_recv_handler(arg);
}
if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 )
{
last_err_msg = "Receive buffer not available";
emacps_recv_handler(arg);
}
break;
case XEMACPS_SEND:
if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 )
{
last_err_msg = "Transmit DMA error";
xNetworkInterfaceInitialise( );
}
if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 )
{
last_err_msg = "Transmit under run";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 )
{
last_err_msg = "Transmit buffer exhausted";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 )
{
last_err_msg = "Transmit retry excessed limits";
HandleTxErrors( xemacpsif );
}
if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 )
{
last_err_msg = "Transmit collision";
emacps_check_tx( xemacpsif );
}
break;
}
}
// Break on this statement and inspect error_msg if you like
if( last_err_msg != NULL )
{
error_msg_count++;
FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) );
}
}
extern XEmacPs_Config mac_config;
void HandleTxErrors(xemacpsif_s *xemacpsif)
{
u32 netctrlreg;
//taskENTER_CRITICAL()
{
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg & (~XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg);
clean_dma_txdescs( xemacpsif );
netctrlreg = XEmacPs_ReadReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET);
netctrlreg = netctrlreg | (XEMACPS_NWCTRL_TXEN_MASK);
XEmacPs_WriteReg(xemacpsif->emacps.Config.BaseAddress,
XEMACPS_NWCTRL_OFFSET, netctrlreg);
}
//taskEXIT_CRITICAL( );
}

View file

@ -1,39 +1,39 @@
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __XEMACPSIF_HW_H_
#define __XEMACPSIF_HW_H_
#include "Zynq/x_emacpsif.h"
//#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
XEmacPs_Config * lookup_config(unsigned mac_base);
//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
int emacps_check_errors( xemacpsif_s *xemacps );
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2010-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __XEMACPSIF_HW_H_
#define __XEMACPSIF_HW_H_
#include "Zynq/x_emacpsif.h"
//#include "lwip/netif.h"
#ifdef __cplusplus
extern "C" {
#endif
XEmacPs_Config * lookup_config(unsigned mac_base);
//void init_emacps(xemacpsif_s *xemacpsif, struct netif *netif);
int emacps_check_errors( xemacpsif_s *xemacps );
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,46 +1,46 @@
/*
* Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __XTOPOLOGY_H_
#define __XTOPOLOGY_H_
#ifdef __cplusplus
extern "C" {
#endif
enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
struct xtopology_t {
unsigned emac_baseaddr;
enum xemac_types emac_type;
unsigned intc_baseaddr;
unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
unsigned scugic_baseaddr; /* valid only for Zynq */
unsigned scugic_emac_intr; /* valid only for GEM */
};
extern int x_topology_n_emacs;
extern struct xtopology_t x_topology[];
int x_topology_find_index(unsigned base);
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2007-2013 Xilinx, Inc. All rights reserved.
*
* Xilinx, Inc.
* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
* COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
* ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
* STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
* IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
* FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
* XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
* THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
* ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
* FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef __XTOPOLOGY_H_
#define __XTOPOLOGY_H_
#ifdef __cplusplus
extern "C" {
#endif
enum xemac_types { xemac_type_unknown = -1, xemac_type_xps_emaclite, xemac_type_xps_ll_temac, xemac_type_axi_ethernet, xemac_type_emacps };
struct xtopology_t {
unsigned emac_baseaddr;
enum xemac_types emac_type;
unsigned intc_baseaddr;
unsigned intc_emac_intr; /* valid only for xemac_type_xps_emaclite */
unsigned scugic_baseaddr; /* valid only for Zynq */
unsigned scugic_emac_intr; /* valid only for GEM */
};
extern int x_topology_n_emacs;
extern struct xtopology_t x_topology[];
int x_topology_find_index(unsigned base);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -1,63 +1,63 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
/* FIX ME. */
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
/* FIX ME. */
return pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
/* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
/* FIX ME. */
return pdFALSE;
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
/* FIX ME. */
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
/* FIX ME. */
return pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
/* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
/* FIX ME. */
return pdFALSE;
}

View file

@ -1,193 +1,135 @@
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "tcpip_adapter.h"
enum if_state_t {
INTERFACE_DOWN = 0,
INTERFACE_UP,
};
static const char *TAG = "NetInterface";
volatile static uint32_t xInterfaceState = INTERFACE_DOWN;
#if ( ipconfigHAS_PRINTF != 0 )
static void prvMonitorResources();
#endif
BaseType_t xNetworkInterfaceInitialise( void )
{
static BaseType_t xMACAdrInitialized = pdFALSE;
uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];
if (xInterfaceState == INTERFACE_UP) {
if (xMACAdrInitialized == pdFALSE) {
esp_wifi_get_mac(ESP_IF_WIFI_STA, ucMACAddress);
FreeRTOS_UpdateMACAddress(ucMACAddress);
xMACAdrInitialized = pdTRUE;
}
return pdTRUE;
}
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
if (pxNetworkBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->xDataLength == 0) {
ESP_LOGE(TAG, "Invalid params");
return pdFALSE;
}
esp_err_t ret;
if (xInterfaceState == INTERFACE_DOWN) {
ESP_LOGD(TAG, "Interface down");
ret = ESP_FAIL;
} else {
ret = esp_wifi_internal_tx(ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
}
}
#if ( ipconfigHAS_PRINTF != 0 )
prvMonitorResources();
#endif
if (xReleaseAfterSend == pdTRUE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return ret == ESP_OK ? pdTRUE : pdFALSE;
}
void vNetworkNotifyIFDown()
{
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
if (xInterfaceState != INTERFACE_DOWN) {
xInterfaceState = INTERFACE_DOWN;
xSendEventStructToIPTask( &xRxEvent, 0 );
}
}
void vNetworkNotifyIFUp()
{
xInterfaceState = INTERFACE_UP;
}
esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
#if ( ipconfigHAS_PRINTF != 0 )
prvMonitorResources();
#endif
if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) {
ESP_LOGD(TAG, "Dropping packet");
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
}
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
ESP_LOGE(TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return ESP_FAIL;
}
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
} else {
ESP_LOGE(TAG, "Failed to get buffer descriptor");
return ESP_FAIL;
}
}
#if ( ipconfigHAS_PRINTF != 0 )
static void prvMonitorResources()
{
static UBaseType_t uxLastMinBufferCount = 0u;
static UBaseType_t uxCurrentBufferCount = 0u;
static size_t uxMinLastSize = 0uL;
size_t uxMinSize;
uxCurrentBufferCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentBufferCount )
{
/* The logging produced below may be helpful
* while tuning +TCP: see how many buffers are in use. */
uxLastMinBufferCount = uxCurrentBufferCount;
FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n",
uxGetNumberOfFreeNetworkBuffers(), uxCurrentBufferCount ) );
}
uxMinSize = xPortGetMinimumEverFreeHeapSize();
if( uxMinLastSize != uxMinSize )
{
uxMinLastSize = uxMinSize;
FreeRTOS_printf( ( "Heap: current %lu lowest %lu\n", xPortGetFreeHeapSize(), uxMinSize ) );
}
#if ( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
static UBaseType_t uxLastMinQueueSpace = 0;
UBaseType_t uxCurrentCount = 0u;
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 */
}
#endif /* ( ipconfigHAS_PRINTF != 0 ) */
/*-----------------------------------------------------------*/
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_wifi_internal.h"
#include "tcpip_adapter.h"
enum if_state_t {
INTERFACE_DOWN = 0,
INTERFACE_UP,
};
static const char *TAG = "NetInterface";
volatile static uint32_t xInterfaceState = INTERFACE_DOWN;
BaseType_t xNetworkInterfaceInitialise( void )
{
static BaseType_t xMACAdrInitialized = pdFALSE;
uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ];
if (xInterfaceState == INTERFACE_UP) {
if (xMACAdrInitialized == pdFALSE) {
esp_wifi_get_mac(ESP_IF_WIFI_STA, ucMACAddress);
FreeRTOS_UpdateMACAddress(ucMACAddress);
xMACAdrInitialized = pdTRUE;
}
return pdTRUE;
}
return pdFALSE;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
if (pxNetworkBuffer == NULL || pxNetworkBuffer->pucEthernetBuffer == NULL || pxNetworkBuffer->xDataLength == 0) {
ESP_LOGE(TAG, "Invalid params");
return pdFALSE;
}
esp_err_t ret;
if (xInterfaceState == INTERFACE_DOWN) {
ESP_LOGD(TAG, "Interface down");
ret = ESP_FAIL;
} else {
ret = esp_wifi_internal_tx(ESP_IF_WIFI_STA, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to tx buffer %p, len %d, err %d", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
}
}
if (xReleaseAfterSend == pdTRUE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return ret == ESP_OK ? pdTRUE : pdFALSE;
}
void vNetworkNotifyIFDown()
{
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
if (xInterfaceState != INTERFACE_DOWN) {
xInterfaceState = INTERFACE_DOWN;
xSendEventStructToIPTask( &xRxEvent, 0 );
}
}
void vNetworkNotifyIFUp()
{
xInterfaceState = INTERFACE_UP;
}
esp_err_t wlanif_input(void *netif, void *buffer, uint16_t len, void *eb)
{
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
if( eConsiderFrameForProcessing( buffer ) != eProcessBuffer ) {
ESP_LOGD(TAG, "Dropping packet");
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
}
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(len, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, buffer, len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
ESP_LOGE(TAG, "Failed to enqueue packet to network stack %p, len %d", buffer, len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return ESP_FAIL;
}
esp_wifi_internal_free_rx_buffer(eb);
return ESP_OK;
} else {
ESP_LOGE(TAG, "Failed to get buffer descriptor");
return ESP_FAIL;
}
}

View file

@ -1,118 +0,0 @@
/*
* Handling of Ethernet PHY's
* PHY's communicate with an EMAC either through
* a Media-Independent Interface (MII), or a Reduced Media-Independent Interface (RMII).
* The EMAC can poll for PHY ports on 32 different addresses. Each of the PHY ports
* shall be treated independently.
*
*/
#ifndef PHYHANDLING_H
#define PHYHANDLING_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef ipconfigPHY_MAX_PORTS
/* There can be at most 32 PHY ports, but in most cases there are 4 or less. */
#define ipconfigPHY_MAX_PORTS 4
#endif
/* A generic user-provided function that reads from the PHY-port at 'xAddress'( 0-based ). A 16-bit value shall be stored in
'*pulValue'. xRegister is the register number ( 0 .. 31 ). In fact all PHY registers are 16-bit.
Return non-zero in case the action failed. */
typedef BaseType_t ( *xApplicationPhyReadHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue );
/* A generic user-provided function that writes 'ulValue' to the
PHY-port at 'xAddress' ( 0-based ). xRegister is the register number ( 0 .. 31 ).
Return non-zero in case the action failed. */
typedef BaseType_t ( *xApplicationPhyWriteHook_t )( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue );
typedef struct xPhyProperties
{
uint8_t ucSpeed;
uint8_t ucMDI_X; /* MDI-X : Medium Dependent Interface - Crossover */
uint8_t ucDuplex;
uint8_t ucSpare;
} PhyProperties_t;
typedef struct xEthernetPhy
{
xApplicationPhyReadHook_t fnPhyRead;
xApplicationPhyWriteHook_t fnPhyWrite;
uint32_t ulPhyIDs[ ipconfigPHY_MAX_PORTS ];
uint8_t ucPhyIndexes[ ipconfigPHY_MAX_PORTS ];
TimeOut_t xLinkStatusTimer;
TickType_t xLinkStatusRemaining;
BaseType_t xPortCount;
uint32_t ulBCRValue;
uint32_t ulACRValue;
uint32_t ulLinkStatusMask;
PhyProperties_t xPhyPreferences;
PhyProperties_t xPhyProperties;
} EthernetPhy_t;
/* Some defines used internally here to indicate preferences about speed, MDIX
(wired direct or crossed), and duplex (half or full). */
/* Values for PhyProperties_t::ucSpeed : */
#define PHY_SPEED_10 1
#define PHY_SPEED_100 2
#define PHY_SPEED_AUTO 3
/* Values for PhyProperties_t::ucMDI_X : */
#define PHY_MDIX_DIRECT 1
#define PHY_MDIX_CROSSED 2
#define PHY_MDIX_AUTO 3
/* Values for PhyProperties_t::ucDuplex : */
#define PHY_DUPLEX_HALF 1
#define PHY_DUPLEX_FULL 2
#define PHY_DUPLEX_AUTO 3
/* ID's of supported PHY's : */
#define PHY_ID_LAN8742A 0x0007c130
#define PHY_ID_LAN8720 0x0007c0f0
#define PHY_ID_KSZ8041 0x000010A1
#define PHY_ID_KSZ8051 0x000010A1
#define PHY_ID_KSZ8081 0x000010A1
#define PHY_ID_KSZ8863 0x00221430
#define PHY_ID_KSZ8081MNXIA 0x00221560
#define PHY_ID_DP83848I 0x20005C90
/* Initialise the struct and assign a PHY-read and -write function. */
void vPhyInitialise( EthernetPhy_t *pxPhyObject, xApplicationPhyReadHook_t fnPhyRead, xApplicationPhyWriteHook_t fnPhyWrite );
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */
BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject );
/* Send a reset command to the connected PHY ports and send configuration. */
BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties );
/* Give a command to start auto negotiation on a set of PHY port's. */
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
/* Do not use auto negotiation but use predefined values from 'pxPhyObject->xPhyPreferences'. */
BaseType_t xPhyFixedValue( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask );
/* Check the current Link Status.
'xHadReception' : make this true if a packet has been received since the
last call to this function. */
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception );
/* Get the bitmask of a given 'EthernetPhy_t'. */
#define xPhyGetMask( pxPhyObject ) \
( ( ( ( uint32_t ) 1u ) << ( pxPhyObject )->xPortCount ) - 1u )
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View file

@ -1,610 +0,0 @@
/**
*
* \file
*
* \brief KS8851SNL driver for SAM.
*
* Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "spi_master.h"
#include "ksz8851snl.h"
#include "ksz8851snl_reg.h"
#include "delay.h"
#include "pio.h"
#include "pio_handler.h"
#include "pdc.h"
#include "conf_eth.h"
/* Clock polarity. */
#define SPI_CLK_POLARITY 0
/* Clock phase. */
#define SPI_CLK_PHASE 1
/* SPI PDC register base. */
Pdc *g_p_spi_pdc = 0;
int lUDPLoggingPrintf( const char *pcFormatString, ... );
/* Temporary buffer for PDC reception. */
uint8_t tmpbuf[1536] __attribute__ ((aligned (16)));
union {
uint64_t ul[2];
uint8_t uc[16];
} cmdBuf, respBuf;
void dbg_add_line( const char *pcFormat, ... );
static void spi_clear_ovres( void );
/**
* \brief Read register content, set bitmask and write back to register.
*
* \param reg the register address to modify.
* \param bits_to_set bitmask to apply.
*/
void ksz8851_reg_setbits(uint16_t reg, uint16_t bits_to_set)
{
uint16_t temp;
temp = ksz8851_reg_read(reg);
temp |= bits_to_set;
ksz8851_reg_write(reg, temp);
}
/**
* \brief Read register content, clear bitmask and write back to register.
*
* \param reg the register address to modify.
* \param bits_to_set bitmask to apply.
*/
void ksz8851_reg_clrbits(uint16_t reg, uint16_t bits_to_clr)
{
uint16_t temp;
temp = ksz8851_reg_read(reg);
temp &= ~(uint32_t) bits_to_clr;
ksz8851_reg_write(reg, temp);
}
/**
* \brief Configure the INTN interrupt.
*/
void configure_intn(void (*p_handler) (uint32_t, uint32_t))
{
// gpio_configure_pin(KSZ8851SNL_INTN_GPIO, PIO_INPUT);
// pio_set_input(PIOA, PIO_PA11_IDX, PIO_PULLUP);
/* Configure PIO clock. */
pmc_enable_periph_clk(INTN_ID);
/* Adjust PIO debounce filter parameters, uses 10 Hz filter. */
pio_set_debounce_filter(INTN_PIO, INTN_PIN_MSK, 10);
/* Initialize PIO interrupt handlers, see PIO definition in board.h. */
pio_handler_set(INTN_PIO, INTN_ID, INTN_PIN_MSK,
INTN_ATTR, p_handler);
/* Enable NVIC interrupts. */
NVIC_SetPriority(INTN_IRQn, INT_PRIORITY_PIO);
NVIC_EnableIRQ((IRQn_Type)INTN_ID);
/* Enable PIO interrupts. */
pio_enable_interrupt(INTN_PIO, INTN_PIN_MSK);
}
/**
* \brief Read a register value.
*
* \param reg the register address to modify.
*
* \return the register value.
*/
uint16_t ksz8851_reg_read(uint16_t reg)
{
pdc_packet_t g_pdc_spi_tx_packet;
pdc_packet_t g_pdc_spi_rx_packet;
uint16_t cmd = 0;
uint16_t res = 0;
int iTryCount = 3;
while( iTryCount-- > 0 )
{
uint32_t ulStatus;
spi_clear_ovres();
/* Move register address to cmd bits 9-2, make 32-bit address. */
cmd = (reg << 2) & REG_ADDR_MASK;
/* Last 2 bits still under "don't care bits" handled with byte enable. */
/* Select byte enable for command. */
if (reg & 2) {
/* Odd word address writes bytes 2 and 3 */
cmd |= (0xc << 10);
} else {
/* Even word address write bytes 0 and 1 */
cmd |= (0x3 << 10);
}
/* Add command read code. */
cmd |= CMD_READ;
cmdBuf.uc[0] = cmd >> 8;
cmdBuf.uc[1] = cmd & 0xff;
cmdBuf.uc[2] = CONFIG_SPI_MASTER_DUMMY;
cmdBuf.uc[3] = CONFIG_SPI_MASTER_DUMMY;
/* Prepare PDC transfer. */
g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
g_pdc_spi_tx_packet.ul_size = 4;
g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
g_pdc_spi_rx_packet.ul_size = 4;
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
for( ;; )
{
ulStatus = spi_read_status( KSZ8851SNL_SPI );
if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
{
break;
}
}
gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
if( ( ulStatus & SPI_SR_OVRES ) == 0 )
{
break;
}
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
lUDPLoggingPrintf( "ksz8851_reg_read: SPI_SR_OVRES\n" );
}
res = (tmpbuf[3] << 8) | tmpbuf[2];
return res;
}
/**
* \brief Write a register value.
*
* \param reg the register address to modify.
* \param wrdata the new register value.
*/
void ksz8851_reg_write(uint16_t reg, uint16_t wrdata)
{
pdc_packet_t g_pdc_spi_tx_packet;
pdc_packet_t g_pdc_spi_rx_packet;
uint16_t cmd = 0;
int iTryCount = 3;
while( iTryCount-- > 0 )
{
uint32_t ulStatus;
spi_clear_ovres();
/* Move register address to cmd bits 9-2, make 32-bit address. */
cmd = (reg << 2) & REG_ADDR_MASK;
/* Last 2 bits still under "don't care bits" handled with byte enable. */
/* Select byte enable for command. */
if (reg & 2) {
/* Odd word address writes bytes 2 and 3 */
cmd |= (0xc << 10);
} else {
/* Even word address write bytes 0 and 1 */
cmd |= (0x3 << 10);
}
/* Add command write code. */
cmd |= CMD_WRITE;
cmdBuf.uc[0] = cmd >> 8;
cmdBuf.uc[1] = cmd & 0xff;
cmdBuf.uc[2] = wrdata & 0xff;
cmdBuf.uc[3] = wrdata >> 8;
/* Prepare PDC transfer. */
g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
g_pdc_spi_tx_packet.ul_size = 4;
g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
g_pdc_spi_rx_packet.ul_size = 4;
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
gpio_set_pin_low(KSZ8851SNL_CSN_GPIO);
spi_disable_interrupt( KSZ8851SNL_SPI, ~0ul );
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
for( ;; )
{
ulStatus = spi_read_status( KSZ8851SNL_SPI );
if( ( ulStatus & ( SPI_SR_OVRES | SPI_SR_ENDRX ) ) != 0 )
{
break;
}
}
gpio_set_pin_high( KSZ8851SNL_CSN_GPIO );
if( ( ulStatus & SPI_SR_OVRES ) == 0 )
{
break;
}
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
lUDPLoggingPrintf( "ksz8851_reg_write: SPI_SR_OVRES\n" );
}
}
static void spi_clear_ovres( void )
{
volatile uint32_t rc;
rc = KSZ8851SNL_SPI->SPI_RDR;
spi_read_status( KSZ8851SNL_SPI );
}
/**
* \brief Read internal fifo buffer.
*
* \param buf the buffer to store the data from the fifo buffer.
* \param len the amount of data to read.
*/
void ksz8851_fifo_read(uint8_t *buf, uint32_t len)
{
pdc_packet_t g_pdc_spi_tx_packet;
pdc_packet_t g_pdc_spi_rx_packet;
pdc_packet_t g_pdc_spi_tx_npacket;
pdc_packet_t g_pdc_spi_rx_npacket;
memset( cmdBuf.uc, '\0', sizeof cmdBuf );
cmdBuf.uc[0] = FIFO_READ;
spi_clear_ovres();
/* Prepare PDC transfer. */
g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
g_pdc_spi_tx_packet.ul_size = 9;
g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
g_pdc_spi_rx_packet.ul_size = 9;
g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
g_pdc_spi_tx_npacket.ul_size = len;
g_pdc_spi_rx_npacket.ul_addr = (uint32_t) buf;
g_pdc_spi_rx_npacket.ul_size = len;
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_RXBUFF | SPI_IER_OVRES);
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
}
/**
* \brief Write internal fifo buffer.
*
* \param buf the buffer to send to the fifo buffer.
* \param ulActualLength the total amount of data to write.
* \param ulFIFOLength the size of the first pbuf to write from the pbuf chain.
*/
void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength)
{
static uint8_t frameID = 0;
pdc_packet_t g_pdc_spi_tx_packet;
pdc_packet_t g_pdc_spi_rx_packet;
pdc_packet_t g_pdc_spi_tx_npacket;
pdc_packet_t g_pdc_spi_rx_npacket;
/* Prepare control word and byte count. */
cmdBuf.uc[0] = FIFO_WRITE;
cmdBuf.uc[1] = frameID++ & 0x3f;
cmdBuf.uc[2] = 0;
cmdBuf.uc[3] = ulActualLength & 0xff;
cmdBuf.uc[4] = ulActualLength >> 8;
spi_clear_ovres();
/* Prepare PDC transfer. */
g_pdc_spi_tx_packet.ul_addr = (uint32_t) cmdBuf.uc;
g_pdc_spi_tx_packet.ul_size = 5;
g_pdc_spi_rx_packet.ul_addr = (uint32_t) respBuf.uc;
g_pdc_spi_rx_packet.ul_size = 5;
g_pdc_spi_tx_npacket.ul_addr = (uint32_t) buf;
g_pdc_spi_tx_npacket.ul_size = ulFIFOLength;
g_pdc_spi_rx_npacket.ul_addr = (uint32_t) tmpbuf;
g_pdc_spi_rx_npacket.ul_size = ulFIFOLength;
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, &g_pdc_spi_tx_npacket);
#if( TX_USES_RECV == 1 )
pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, &g_pdc_spi_rx_npacket);
spi_enable_interrupt(KSZ8851SNL_SPI, SPI_IER_ENDRX | SPI_IER_OVRES);
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
#else
spi_enable_interrupt(KSZ8851SNL_SPI, SPI_SR_TXBUFE | SPI_IER_OVRES);
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_TXTEN);
#endif
}
/**
* \brief Write dummy data to the internal fifo buffer.
*
* \param len the amount of dummy data to write.
*/
void ksz8851_fifo_dummy(uint32_t len)
{
pdc_packet_t g_pdc_spi_tx_packet;
pdc_packet_t g_pdc_spi_rx_packet;
/* Prepare PDC transfer. */
g_pdc_spi_tx_packet.ul_addr = (uint32_t) tmpbuf;
g_pdc_spi_tx_packet.ul_size = len;
g_pdc_spi_rx_packet.ul_addr = (uint32_t) tmpbuf;
g_pdc_spi_rx_packet.ul_size = len;
pdc_disable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
pdc_tx_init(g_p_spi_pdc, &g_pdc_spi_tx_packet, NULL);
pdc_rx_init(g_p_spi_pdc, &g_pdc_spi_rx_packet, NULL);
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
while (!(spi_read_status(KSZ8851SNL_SPI) & SPI_SR_ENDRX))
;
}
void ksz8851snl_set_registers(void)
{
/* Init step2-4: write QMU MAC address (low, middle then high). */
ksz8851_reg_write(REG_MAC_ADDR_0, (ETHERNET_CONF_ETHADDR4 << 8) | ETHERNET_CONF_ETHADDR5);
ksz8851_reg_write(REG_MAC_ADDR_2, (ETHERNET_CONF_ETHADDR2 << 8) | ETHERNET_CONF_ETHADDR3);
ksz8851_reg_write(REG_MAC_ADDR_4, (ETHERNET_CONF_ETHADDR0 << 8) | ETHERNET_CONF_ETHADDR1);
/* Init step5: enable QMU Transmit Frame Data Pointer Auto Increment. */
ksz8851_reg_write(REG_TX_ADDR_PTR, ADDR_PTR_AUTO_INC);
/* Init step6: configure QMU transmit control register. */
ksz8851_reg_write(REG_TX_CTRL,
TX_CTRL_ICMP_CHECKSUM |
TX_CTRL_UDP_CHECKSUM |
TX_CTRL_TCP_CHECKSUM |
TX_CTRL_IP_CHECKSUM |
TX_CTRL_FLOW_ENABLE |
TX_CTRL_PAD_ENABLE |
TX_CTRL_CRC_ENABLE
);
/* Init step7: enable QMU Receive Frame Data Pointer Auto Increment. */
ksz8851_reg_write(REG_RX_ADDR_PTR, ADDR_PTR_AUTO_INC);
/* Init step8: configure QMU Receive Frame Threshold for one frame. */
ksz8851_reg_write(REG_RX_FRAME_CNT_THRES, 1);
/* Init step9: configure QMU receive control register1. */
ksz8851_reg_write(REG_RX_CTRL1,
RX_CTRL_UDP_CHECKSUM |
RX_CTRL_TCP_CHECKSUM |
RX_CTRL_IP_CHECKSUM |
RX_CTRL_MAC_FILTER |
RX_CTRL_FLOW_ENABLE |
RX_CTRL_BROADCAST |
RX_CTRL_ALL_MULTICAST|
RX_CTRL_UNICAST);
// ksz8851_reg_write(REG_RX_CTRL1,
// RX_CTRL_UDP_CHECKSUM |
// RX_CTRL_TCP_CHECKSUM |
// RX_CTRL_IP_CHECKSUM |
// RX_CTRL_FLOW_ENABLE |
// RX_CTRL_PROMISCUOUS);
ksz8851_reg_write(REG_RX_CTRL2,
RX_CTRL_IPV6_UDP_NOCHECKSUM |
RX_CTRL_UDP_LITE_CHECKSUM |
RX_CTRL_ICMP_CHECKSUM |
RX_CTRL_BURST_LEN_FRAME);
//#define RXQ_TWOBYTE_OFFSET (0x0200) /* Enable adding 2-byte before frame header for IP aligned with DWORD */
#warning Remember to try the above option to get a 2-byte offset
/* Init step11: configure QMU receive queue: trigger INT and auto-dequeue frame. */
ksz8851_reg_write( REG_RXQ_CMD, RXQ_CMD_CNTL | RXQ_TWOBYTE_OFFSET );
/* Init step12: adjust SPI data output delay. */
ksz8851_reg_write(REG_BUS_CLOCK_CTRL, BUS_CLOCK_166 | BUS_CLOCK_DIVIDEDBY_1);
/* Init step13: restart auto-negotiation. */
ksz8851_reg_setbits(REG_PORT_CTRL, PORT_AUTO_NEG_RESTART);
/* Init step13.1: force link in half duplex if auto-negotiation failed. */
if ((ksz8851_reg_read(REG_PORT_CTRL) & PORT_AUTO_NEG_RESTART) != PORT_AUTO_NEG_RESTART)
{
ksz8851_reg_clrbits(REG_PORT_CTRL, PORT_FORCE_FULL_DUPLEX);
}
/* Init step14: clear interrupt status. */
ksz8851_reg_write(REG_INT_STATUS, 0xFFFF);
/* Init step15: set interrupt mask. */
ksz8851_reg_write(REG_INT_MASK, INT_RX);
/* Init step16: enable QMU Transmit. */
ksz8851_reg_setbits(REG_TX_CTRL, TX_CTRL_ENABLE);
/* Init step17: enable QMU Receive. */
ksz8851_reg_setbits(REG_RX_CTRL1, RX_CTRL_ENABLE);
}
/**
* \brief KSZ8851SNL initialization function.
*
* \return 0 on success, 1 on communication error.
*/
uint32_t ksz8851snl_init(void)
{
uint32_t count = 10;
uint16_t dev_id = 0;
uint8_t id_ok = 0;
/* Configure the SPI peripheral. */
spi_enable_clock(KSZ8851SNL_SPI);
spi_disable(KSZ8851SNL_SPI);
spi_reset(KSZ8851SNL_SPI);
spi_set_master_mode(KSZ8851SNL_SPI);
spi_disable_mode_fault_detect(KSZ8851SNL_SPI);
spi_set_peripheral_chip_select_value(KSZ8851SNL_SPI, ~(uint32_t)(1UL << KSZ8851SNL_CS_PIN));
spi_set_fixed_peripheral_select(KSZ8851SNL_SPI);
//spi_disable_peripheral_select_decode(KSZ8851SNL_SPI);
spi_set_clock_polarity(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_POLARITY);
spi_set_clock_phase(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, SPI_CLK_PHASE);
spi_set_bits_per_transfer(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN,
SPI_CSR_BITS_8_BIT);
spi_set_baudrate_div(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, (sysclk_get_cpu_hz() / KSZ8851SNL_CLOCK_SPEED));
// spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, CONFIG_SPI_MASTER_DELAY_BS,
// CONFIG_SPI_MASTER_DELAY_BCT);
spi_set_transfer_delay(KSZ8851SNL_SPI, KSZ8851SNL_CS_PIN, 0, 0);
spi_enable(KSZ8851SNL_SPI);
/* Get pointer to UART PDC register base. */
g_p_spi_pdc = spi_get_pdc_base(KSZ8851SNL_SPI);
pdc_enable_transfer(g_p_spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN);
/* Control RSTN and CSN pin from the driver. */
gpio_configure_pin(KSZ8851SNL_CSN_GPIO, KSZ8851SNL_CSN_FLAGS);
gpio_set_pin_high(KSZ8851SNL_CSN_GPIO);
gpio_configure_pin(KSZ8851SNL_RSTN_GPIO, KSZ8851SNL_RSTN_FLAGS);
/* Reset the Micrel in a proper state. */
while( count-- )
{
/* Perform hardware reset with respect to the reset timing from the datasheet. */
gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
vTaskDelay(2);
gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
vTaskDelay(2);
/* Init step1: read chip ID. */
dev_id = ksz8851_reg_read(REG_CHIP_ID);
if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
{
id_ok = 1;
break;
}
}
if( id_ok != 0 )
{
ksz8851snl_set_registers();
}
return id_ok ? 1 : -1;
}
uint32_t ksz8851snl_reinit(void)
{
uint32_t count = 10;
uint16_t dev_id = 0;
uint8_t id_ok = 0;
/* Reset the Micrel in a proper state. */
while( count-- )
{
/* Perform hardware reset with respect to the reset timing from the datasheet. */
gpio_set_pin_low(KSZ8851SNL_RSTN_GPIO);
vTaskDelay(2);
gpio_set_pin_high(KSZ8851SNL_RSTN_GPIO);
vTaskDelay(2);
/* Init step1: read chip ID. */
dev_id = ksz8851_reg_read(REG_CHIP_ID);
if( ( dev_id & 0xFFF0 ) == CHIP_ID_8851_16 )
{
id_ok = 1;
break;
}
}
if( id_ok != 0 )
{
ksz8851snl_set_registers();
}
return id_ok ? 1 : -1;
}
uint32_t ksz8851snl_reset_rx( void )
{
uint16_t usValue;
usValue = ksz8851_reg_read(REG_RX_CTRL1);
usValue &= ~( ( uint16_t ) RX_CTRL_ENABLE | RX_CTRL_FLUSH_QUEUE );
ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 2 );
ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
ksz8851_reg_write( REG_RX_CTRL1, usValue ); vTaskDelay( 1 );
ksz8851_reg_write( REG_RX_CTRL1, usValue | RX_CTRL_ENABLE ); vTaskDelay( 1 );
return ( uint32_t )usValue;
}
uint32_t ksz8851snl_reset_tx( void )
{
uint16_t usValue;
usValue = ksz8851_reg_read( REG_TX_CTRL );
usValue &= ~( ( uint16_t ) TX_CTRL_ENABLE | TX_CTRL_FLUSH_QUEUE );
ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 2 );
ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_FLUSH_QUEUE ); vTaskDelay( 1 );
ksz8851_reg_write( REG_TX_CTRL, usValue ); vTaskDelay( 1 );
ksz8851_reg_write( REG_TX_CTRL, usValue | TX_CTRL_ENABLE ); vTaskDelay( 1 );
return ( uint32_t )usValue;
}

View file

@ -1,67 +0,0 @@
/**
*
* \file
*
* \brief KS8851SNL driver for SAM.
*
* Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef KSZ8851SNL_H_INCLUDED
#define KSZ8851SNL_H_INCLUDED
#include "gpio.h"
void configure_intn(void (*p_handler) (uint32_t, uint32_t));
void ksz8851_reg_setbits(uint16_t reg, uint16_t bits_to_set);
void ksz8851_reg_clrbits(uint16_t reg, uint16_t bits_to_clr);
void ksz8851_fifo_read(uint8_t *buf, uint32_t len);
void ksz8851_fifo_write(uint8_t *buf, uint32_t ulActualLength, uint32_t ulFIFOLength);
void ksz8851_fifo_dummy(uint32_t len);
void ksz8851_reg_write(uint16_t reg, uint16_t wrdata);
uint16_t ksz8851_reg_read(uint16_t reg);
uint32_t ksz8851snl_init(void);
uint32_t ksz8851snl_reinit(void);
uint32_t ksz8851snl_reset_rx( void );
uint32_t ksz8851snl_reset_tx( void );
#endif /* KSZ8851SNL_H_INCLUDED */

View file

@ -1,473 +0,0 @@
/**
*
* \file
*
* \brief KS8851SNL registers definitions.
*
* Copyright (c) 2013-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
/*
* Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/
#ifndef KSZ8851SNL_REG_H_INCLUDED
#define KSZ8851SNL_REG_H_INCLUDED
#define REG_ADDR_MASK (0x3F0) /* Register address mask */
#define OPCODE_MASK (3 << 14)
#define CMD_READ (0 << 14)
#define CMD_WRITE (1 << 14)
#define FIFO_READ (0x80)
#define FIFO_WRITE (0xC0)
/*
* MAC Registers
* (Offset 0x00 - 0x25)
*/
#define REG_BUS_ERROR_STATUS (0x06) /* BESR */
#define BUS_ERROR_IBEC (0x8000)
#define BUS_ERROR_IBECV_MASK (0x7800) /* Default IPSec clock at 166Mhz */
#define REG_CHIP_CFG_STATUS (0x08) /* CCFG */
#define LITTLE_ENDIAN_BUS_MODE (0x0400) /* Bus in little endian mode */
#define EEPROM_PRESENCE (0x0200) /* External EEPROM is used */
#define SPI_BUS_MODE (0x0100) /* In SPI bus mode */
#define DATA_BUS_8BIT (0x0080) /* In 8-bit bus mode operation */
#define DATA_BUS_16BIT (0x0040) /* In 16-bit bus mode operation */
#define DATA_BUS_32BIT (0x0020) /* In 32-bit bus mode operation */
#define MULTIPLEX_MODE (0x0010) /* Data and address bus are shared */
#define CHIP_PACKAGE_128PIN (0x0008) /* 128-pin package */
#define CHIP_PACKAGE_80PIN (0x0004) /* 80-pin package */
#define CHIP_PACKAGE_48PIN (0x0002) /* 48-pin package */
#define CHIP_PACKAGE_32PIN (0x0001) /* 32-pin package for SPI host interface only */
#define REG_MAC_ADDR_0 (0x10) /* MARL */
#define REG_MAC_ADDR_1 (0x11) /* MARL */
#define REG_MAC_ADDR_2 (0x12) /* MARM */
#define REG_MAC_ADDR_3 (0x13) /* MARM */
#define REG_MAC_ADDR_4 (0x14) /* MARH */
#define REG_MAC_ADDR_5 (0x15) /* MARH */
#define REG_BUS_CLOCK_CTRL (0x20) /* OBCR */
#define BUS_CLOCK_166 (0x0004) /* 166 MHz on-chip bus clock (defaul is 125MHz) */
#define BUS_CLOCK_DIVIDEDBY_5 (0x0003) /* Bus clock devided by 5 */
#define BUS_CLOCK_DIVIDEDBY_3 (0x0002) /* Bus clock devided by 3 */
#define BUS_CLOCK_DIVIDEDBY_2 (0x0001) /* Bus clock devided by 2 */
#define BUS_CLOCK_DIVIDEDBY_1 (0x0000) /* Bus clock devided by 1 */
#define BUS_CLOCK_DIVIDED_MASK (0x0003) /* Bus clock devider mask */
#define BUS_SPEED_166_MHZ (0x0004) /* Set bus speed to 166 MHz */
#define BUS_SPEED_125_MHZ (0x0000) /* Set bus speed to 125 MHz */
#define BUS_SPEED_83_MHZ (0x0005) /* Set bus speed to 83 MHz (166/2)*/
#define BUS_SPEED_62_5_MHZ (0x0001) /* Set bus speed to 62.5 MHz (125/2) */
#define BUS_SPEED_53_3_MHZ (0x0006) /* Set bus speed to 53.3 MHz (166/3) */
#define BUS_SPEED_41_7_MHZ (0x0002) /* Set bus speed to 41.67 MHz (125/3) */
#define BUS_SPEED_33_2_MHZ (0x0007) /* Set bus speed to 33.2 MHz (166/5) */
#define BUS_SPEED_25_MHZ (0x0003) /* Set bus speed to 25 MHz (125/5) */
#define REG_EEPROM_CTRL (0x22) /* EEPCR */
#define EEPROM_ACCESS_ENABLE (0x0010) /* Enable software to access EEPROM through bit 3 to bit 0 */
#define EEPROM_DATA_IN (0x0008) /* Data receive from EEPROM (EEDI pin) */
#define EEPROM_DATA_OUT (0x0004) /* Data transmit to EEPROM (EEDO pin) */
#define EEPROM_SERIAL_CLOCK (0x0002) /* Serial clock (EESK pin) */
#define EEPROM_CHIP_SELECT (0x0001) /* EEPROM chip select (EECS pin) */
#define REG_MEM_BIST_INFO (0x24) /* MBIR */
#define TX_MEM_TEST_FINISHED (0x1000) /* TX memeory BIST test finish */
#define TX_MEM_TEST_FAILED (0x0800) /* TX memory BIST test fail */
#define TX_MEM_TEST_FAILED_COUNT (0x0700) /* TX memory BIST test fail count */
#define RX_MEM_TEST_FINISHED (0x0010) /* RX memory BIST test finish */
#define RX_MEM_TEST_FAILED (0x0008) /* RX memory BIST test fail */
#define RX_MEM_TEST_FAILED_COUNT (0x0003) /* RX memory BIST test fail count */
#define REG_RESET_CTRL (0x26) /* GRR */
#define QMU_SOFTWARE_RESET (0x0002) /* QMU soft reset (clear TxQ, RxQ) */
#define GLOBAL_SOFTWARE_RESET (0x0001) /* Global soft reset (PHY, MAC, QMU) */
/*
* Wake On Lan Control Registers
* (Offset 0x2A - 0x6B)
*/
#define REG_WOL_CTRL (0x2A) /* WFCR */
#define WOL_MAGIC_ENABLE (0x0080) /* Enable the magic packet pattern detection */
#define WOL_FRAME3_ENABLE (0x0008) /* Enable the wake up frame 3 pattern detection */
#define WOL_FRAME2_ENABLE (0x0004) /* Enable the wake up frame 2 pattern detection */
#define WOL_FRAME1_ENABLE (0x0002) /* Enable the wake up frame 1 pattern detection */
#define WOL_FRAME0_ENABLE (0x0001) /* Enable the wake up frame 0 pattern detection */
#define REG_WOL_FRAME0_CRC0 (0x30) /* WF0CRC0 */
#define REG_WOL_FRAME0_CRC1 (0x32) /* WF0CRC1 */
#define REG_WOL_FRAME0_BYTE_MASK0 (0x34) /* WF0BM0 */
#define REG_WOL_FRAME0_BYTE_MASK1 (0x36) /* WF0BM1 */
#define REG_WOL_FRAME0_BYTE_MASK2 (0x38) /* WF0BM2 */
#define REG_WOL_FRAME0_BYTE_MASK3 (0x3A) /* WF0BM3 */
#define REG_WOL_FRAME1_CRC0 (0x40) /* WF1CRC0 */
#define REG_WOL_FRAME1_CRC1 (0x42) /* WF1CRC1 */
#define REG_WOL_FRAME1_BYTE_MASK0 (0x44) /* WF1BM0 */
#define REG_WOL_FRAME1_BYTE_MASK1 (0x46) /* WF1BM1 */
#define REG_WOL_FRAME1_BYTE_MASK2 (0x48) /* WF1BM2 */
#define REG_WOL_FRAME1_BYTE_MASK3 (0x4A) /* WF1BM3 */
#define REG_WOL_FRAME2_CRC0 (0x50) /* WF2CRC0 */
#define REG_WOL_FRAME2_CRC1 (0x52) /* WF2CRC1 */
#define REG_WOL_FRAME2_BYTE_MASK0 (0x54) /* WF2BM0 */
#define REG_WOL_FRAME2_BYTE_MASK1 (0x56) /* WF2BM1 */
#define REG_WOL_FRAME2_BYTE_MASK2 (0x58) /* WF2BM2 */
#define REG_WOL_FRAME2_BYTE_MASK3 (0x5A) /* WF2BM3 */
#define REG_WOL_FRAME3_CRC0 (0x60) /* WF3CRC0 */
#define REG_WOL_FRAME3_CRC1 (0x62) /* WF3CRC1 */
#define REG_WOL_FRAME3_BYTE_MASK0 (0x64) /* WF3BM0 */
#define REG_WOL_FRAME3_BYTE_MASK1 (0x66) /* WF3BM1 */
#define REG_WOL_FRAME3_BYTE_MASK2 (0x68) /* WF3BM2 */
#define REG_WOL_FRAME3_BYTE_MASK3 (0x6A) /* WF3BM3 */
/*
* Transmit/Receive Control Registers
* (Offset 0x70 - 0x9F)
*/
/* Transmit Frame Header */
#define REG_QDR_DUMMY (0x00) /* Dummy address to access QMU RxQ, TxQ */
#define TX_CTRL_INTERRUPT_ON (0x8000) /* Transmit Interrupt on Completion */
#define REG_TX_CTRL (0x70) /* TXCR */
#define TX_CTRL_ICMP_CHECKSUM (0x0100) /* Enable ICMP frame checksum generation */
#define TX_CTRL_UDP_CHECKSUM (0x0080) /* Enable UDP frame checksum generation */
#define TX_CTRL_TCP_CHECKSUM (0x0040) /* Enable TCP frame checksum generation */
#define TX_CTRL_IP_CHECKSUM (0x0020) /* Enable IP frame checksum generation */
#define TX_CTRL_FLUSH_QUEUE (0x0010) /* Clear transmit queue, reset tx frame pointer */
#define TX_CTRL_FLOW_ENABLE (0x0008) /* Enable transmit flow control */
#define TX_CTRL_PAD_ENABLE (0x0004) /* Eanble adding a padding to a packet shorter than 64 bytes */
#define TX_CTRL_CRC_ENABLE (0x0002) /* Enable adding a CRC to the end of transmit frame */
#define TX_CTRL_ENABLE (0x0001) /* Enable tranmsit */
#define REG_TX_STATUS (0x72) /* TXSR */
#define TX_STAT_LATE_COL (0x2000) /* Tranmsit late collision occurs */
#define TX_STAT_MAX_COL (0x1000) /* Tranmsit maximum collision is reached */
#define TX_FRAME_ID_MASK (0x003F) /* Transmit frame ID mask */
#define TX_STAT_ERRORS ( TX_STAT_MAX_COL | TX_STAT_LATE_COL )
#define REG_RX_CTRL1 (0x74) /* RXCR1 */
#define RX_CTRL_FLUSH_QUEUE (0x8000) /* Clear receive queue, reset rx frame pointer */
#define RX_CTRL_UDP_CHECKSUM (0x4000) /* Enable UDP frame checksum verification */
#define RX_CTRL_TCP_CHECKSUM (0x2000) /* Enable TCP frame checksum verification */
#define RX_CTRL_IP_CHECKSUM (0x1000) /* Enable IP frame checksum verification */
#define RX_CTRL_MAC_FILTER (0x0800) /* Receive with address that pass MAC address filtering */
#define RX_CTRL_FLOW_ENABLE (0x0400) /* Enable receive flow control */
#define RX_CTRL_BAD_PACKET (0x0200) /* Eanble receive CRC error frames */
#define RX_CTRL_MULTICAST (0x0100) /* Receive multicast frames that pass the CRC hash filtering */
#define RX_CTRL_BROADCAST (0x0080) /* Receive all the broadcast frames */
#define RX_CTRL_ALL_MULTICAST (0x0040) /* Receive all the multicast frames (including broadcast frames) */
#define RX_CTRL_UNICAST (0x0020) /* Receive unicast frames that match the device MAC address */
#define RX_CTRL_PROMISCUOUS (0x0010) /* Receive all incoming frames, regardless of frame's DA */
#define RX_CTRL_STRIP_CRC (0x0008) /* Enable strip CRC on the received frames */
#define RX_CTRL_INVERSE_FILTER (0x0002) /* Receive with address check in inverse filtering mode */
#define RX_CTRL_ENABLE (0x0001) /* Enable receive */
/* Address filtering scheme mask */
#define RX_CTRL_FILTER_MASK ( RX_CTRL_INVERSE_FILTER | RX_CTRL_PROMISCUOUS | RX_CTRL_MULTICAST | RX_CTRL_MAC_FILTER )
#define REG_RX_CTRL2 (0x76) /* RXCR2 */
#define RX_CTRL_IPV6_UDP_NOCHECKSUM (0x0010) /* No checksum generation and verification if IPv6 UDP is fragment */
#define RX_CTRL_IPV6_UDP_CHECKSUM (0x0008) /* Receive pass IPv6 UDP frame with UDP checksum is zero */
#define RX_CTRL_UDP_LITE_CHECKSUM (0x0004) /* Enable UDP Lite frame checksum generation and verification */
#define RX_CTRL_ICMP_CHECKSUM (0x0002) /* Enable ICMP frame checksum verification */
#define RX_CTRL_BLOCK_MAC (0x0001) /* Receive drop frame if the SA is same as device MAC address */
#define RX_CTRL_BURST_LEN_MASK (0x00e0) /* SRDBL SPI Receive Data Burst Length */
#define RX_CTRL_BURST_LEN_4 (0x0000)
#define RX_CTRL_BURST_LEN_8 (0x0020)
#define RX_CTRL_BURST_LEN_16 (0x0040)
#define RX_CTRL_BURST_LEN_32 (0x0060)
#define RX_CTRL_BURST_LEN_FRAME (0x0080)
#define REG_TX_MEM_INFO (0x78) /* TXMIR */
#define TX_MEM_AVAILABLE_MASK (0x1FFF) /* The amount of memory available in TXQ */
#define REG_RX_FHR_STATUS (0x7C) /* RXFHSR */
#define RX_VALID (0x8000) /* Frame in the receive packet memory is valid */
#define RX_ICMP_ERROR (0x2000) /* ICMP checksum field doesn't match */
#define RX_IP_ERROR (0x1000) /* IP checksum field doesn't match */
#define RX_TCP_ERROR (0x0800) /* TCP checksum field doesn't match */
#define RX_UDP_ERROR (0x0400) /* UDP checksum field doesn't match */
#define RX_BROADCAST (0x0080) /* Received frame is a broadcast frame */
#define RX_MULTICAST (0x0040) /* Received frame is a multicast frame */
#define RX_UNICAST (0x0020) /* Received frame is a unicast frame */
#define RX_PHY_ERROR (0x0010) /* Received frame has runt error */
#define RX_FRAME_ETHER (0x0008) /* Received frame is an Ethernet-type frame */
#define RX_TOO_LONG (0x0004) /* Received frame length exceeds max size 0f 2048 bytes */
#define RX_RUNT_ERROR (0x0002) /* Received frame was demaged by a collision */
#define RX_BAD_CRC (0x0001) /* Received frame has a CRC error */
#define RX_ERRORS ( RX_BAD_CRC | RX_TOO_LONG | RX_RUNT_ERROR | RX_PHY_ERROR | \
RX_ICMP_ERROR | RX_IP_ERROR | RX_TCP_ERROR | RX_UDP_ERROR )
#define REG_RX_FHR_BYTE_CNT (0x7E) /* RXFHBCR */
#define RX_BYTE_CNT_MASK (0x0FFF) /* Received frame byte size mask */
#define REG_TXQ_CMD (0x80) /* TXQCR */
#define TXQ_AUTO_ENQUEUE (0x0004) /* Enable enqueue tx frames from tx buffer automatically */
#define TXQ_MEM_AVAILABLE_INT (0x0002) /* Enable generate interrupt when tx memory is available */
#define TXQ_ENQUEUE (0x0001) /* Enable enqueue tx frames one frame at a time */
#define REG_RXQ_CMD (0x82) /* RXQCR */
#define RXQ_STAT_TIME_INT (0x1000) /* RX interrupt is occured by timer duration */
#define RXQ_STAT_BYTE_CNT_INT (0x0800) /* RX interrupt is occured by byte count threshold */
#define RXQ_STAT_FRAME_CNT_INT (0x0400) /* RX interrupt is occured by frame count threshold */
#define RXQ_TWOBYTE_OFFSET (0x0200) /* Enable adding 2-byte before frame header for IP aligned with DWORD */
#define RXQ_TIME_INT (0x0080) /* Enable RX interrupt by timer duration */
#define RXQ_BYTE_CNT_INT (0x0040) /* Enable RX interrupt by byte count threshold */
#define RXQ_FRAME_CNT_INT (0x0020) /* Enable RX interrupt by frame count threshold */
#define RXQ_AUTO_DEQUEUE (0x0010) /* Enable release rx frames from rx buffer automatically */
#define RXQ_START (0x0008) /* Start QMU transfer operation */
#define RXQ_CMD_FREE_PACKET (0x0001) /* Manual dequeue (release the current frame from RxQ) */
#define RXQ_CMD_CNTL (RXQ_FRAME_CNT_INT|RXQ_AUTO_DEQUEUE)
#define REG_TX_ADDR_PTR (0x84) /* TXFDPR */
#define REG_RX_ADDR_PTR (0x86) /* RXFDPR */
#define ADDR_PTR_AUTO_INC (0x4000) /* Enable Frame data pointer increments automatically */
#define ADDR_PTR_MASK (0x03ff) /* Address pointer mask */
#define REG_RX_TIME_THRES (0x8C) /* RXDTTR */
#define RX_TIME_THRESHOLD_MASK (0xFFFF) /* Set receive timer duration threshold */
#define REG_RX_BYTE_CNT_THRES (0x8E) /* RXDBCTR */
#define RX_BYTE_THRESHOLD_MASK (0xFFFF) /* Set receive byte count threshold */
#define REG_INT_MASK (0x90) /* IER */
#define INT_PHY (0x8000) /* Enable link change interrupt */
#define INT_TX (0x4000) /* Enable transmit done interrupt */
#define INT_RX (0x2000) /* Enable receive interrupt */
#define INT_RX_OVERRUN (0x0800) /* Enable receive overrun interrupt */
#define INT_TX_STOPPED (0x0200) /* Enable transmit process stopped interrupt */
#define INT_RX_STOPPED (0x0100) /* Enable receive process stopped interrupt */
#define INT_TX_SPACE (0x0040) /* Enable transmit space available interrupt */
#define INT_RX_WOL_FRAME (0x0020) /* Enable WOL on receive wake-up frame detect interrupt */
#define INT_RX_WOL_MAGIC (0x0010) /* Enable WOL on receive magic packet detect interrupt */
#define INT_RX_WOL_LINKUP (0x0008) /* Enable WOL on link up detect interrupt */
#define INT_RX_WOL_ENERGY (0x0004) /* Enable WOL on energy detect interrupt */
#define INT_RX_SPI_ERROR (0x0002) /* Enable receive SPI bus error interrupt */
#define INT_RX_WOL_DELAY_ENERGY (0x0001) /* Enable WOL on delay energy detect interrupt */
#define INT_MASK ( INT_RX | INT_TX | INT_PHY )
#define REG_INT_STATUS (0x92) /* ISR */
#define REG_RX_FRAME_CNT_THRES (0x9C) /* RXFCTFC */
#define RX_FRAME_CNT_MASK (0xFF00) /* Received frame count mask */
#define RX_FRAME_THRESHOLD_MASK (0x00FF) /* Set receive frame count threshold mask */
#define REG_TX_TOTAL_FRAME_SIZE (0x9E) /* TXNTFSR */
#define TX_TOTAL_FRAME_SIZE_MASK (0xFFFF) /* Set next total tx frame size mask */
/*
* MAC Address Hash Table Control Registers
* (Offset 0xA0 - 0xA7)
*/
#define REG_MAC_HASH_0 (0xA0) /* MAHTR0 */
#define REG_MAC_HASH_1 (0xA1)
#define REG_MAC_HASH_2 (0xA2) /* MAHTR1 */
#define REG_MAC_HASH_3 (0xA3)
#define REG_MAC_HASH_4 (0xA4) /* MAHTR2 */
#define REG_MAC_HASH_5 (0xA5)
#define REG_MAC_HASH_6 (0xA6) /* MAHTR3 */
#define REG_MAC_HASH_7 (0xA7)
/*
* QMU Receive Queue Watermark Control Registers
* (Offset 0xB0 - 0xB5)
*/
#define REG_RX_LOW_WATERMARK (0xB0) /* FCLWR */
#define RX_LOW_WATERMARK_MASK (0x0FFF) /* Set QMU RxQ low watermark mask */
#define REG_RX_HIGH_WATERMARK (0xB2) /* FCHWR */
#define RX_HIGH_WATERMARK_MASK (0x0FFF) /* Set QMU RxQ high watermark mask */
#define REG_RX_OVERRUN_WATERMARK (0xB4) /* FCOWR */
#define RX_OVERRUN_WATERMARK_MASK (0x0FFF) /* Set QMU RxQ overrun watermark mask */
/*
* Global Control Registers
* (Offset 0xC0 - 0xD3)
*/
#define REG_CHIP_ID (0xC0) /* CIDER */
#define CHIP_ID_MASK (0xFFF0) /* Family ID and chip ID mask */
#define REVISION_MASK (0x000E) /* Chip revision mask */
#define CHIP_ID_SHIFT (4)
#define REVISION_SHIFT (1)
#define CHIP_ID_8851_16 (0x8870) /* KS8851-16/32MQL chip ID */
#define REG_LED_CTRL (0xC6) /* CGCR */
#define LED_CTRL_SEL1 (0x8000) /* Select LED3/LED2/LED1/LED0 indication */
#define LED_CTRL_SEL0 (0x0200) /* Select LED3/LED2/LED1/LED0 indication */
#define REG_IND_IACR (0xC8) /* IACR */
#define TABLE_READ (0x1000) /* Indirect read */
#define TABLE_MIB (0x0C00) /* Select MIB counter table */
#define TABLE_ENTRY_MASK (0x001F) /* Set table entry to access */
#define REG_IND_DATA_LOW (0xD0) /* IADLR */
#define REG_IND_DATA_HIGH (0xD2) /* IADHR */
/*
* Power Management Control Registers
* (Offset 0xD4 - 0xD7)
*/
#define REG_POWER_CNTL (0xD4) /* PMECR */
#define PME_DELAY_ENABLE (0x4000) /* Enable the PME output pin assertion delay */
#define PME_ACTIVE_HIGHT (0x1000) /* PME output pin is active high */
#define PME_FROM_WKFRAME (0x0800) /* PME asserted when wake-up frame is detected */
#define PME_FROM_MAGIC (0x0400) /* PME asserted when magic packet is detected */
#define PME_FROM_LINKUP (0x0200) /* PME asserted when link up is detected */
#define PME_FROM_ENERGY (0x0100) /* PME asserted when energy is detected */
#define PME_EVENT_MASK (0x0F00) /* PME asserted event mask */
#define WAKEUP_AUTO_ENABLE (0x0080) /* Enable auto wake-up in energy mode */
#define WAKEUP_NORMAL_AUTO_ENABLE (0x0040) /* Enable auto goto normal mode from energy detecion mode */
#define WAKEUP_FROM_WKFRAME (0x0020) /* Wake-up from wake-up frame event detected */
#define WAKEUP_FROM_MAGIC (0x0010) /* Wake-up from magic packet event detected */
#define WAKEUP_FROM_LINKUP (0x0008) /* Wake-up from link up event detected */
#define WAKEUP_FROM_ENERGY (0x0004) /* Wake-up from energy event detected */
#define WAKEUP_EVENT_MASK (0x003C) /* Wake-up event mask */
#define POWER_STATE_D1 (0x0003) /* Power saving mode */
#define POWER_STATE_D3 (0x0002) /* Power down mode */
#define POWER_STATE_D2 (0x0001) /* Power detection mode */
#define POWER_STATE_D0 (0x0000) /* Normal operation mode (default) */
#define POWER_STATE_MASK (0x0003) /* Power management mode mask */
#define REG_WAKEUP_TIME (0xD6) /* GSWUTR */
#define WAKEUP_TIME (0xFF00) /* Min time (sec) wake-uo after detected energy */
#define GOSLEEP_TIME (0x00FF) /* Min time (sec) before goto sleep when in energy mode */
/*
* PHY Control Registers
* (Offset 0xD8 - 0xF9)
*/
#define REG_PHY_RESET (0xD8) /* PHYRR */
#define PHY_RESET (0x0001) /* Reset PHY */
#define REG_PHY_CNTL (0xE4) /* P1MBCR */
#define PHY_SPEED_100MBIT (0x2000) /* Force PHY 100Mbps */
#define PHY_AUTO_NEG_ENABLE (0x1000) /* Enable PHY auto-negotiation */
#define PHY_POWER_DOWN (0x0800) /* Set PHY power-down */
#define PHY_AUTO_NEG_RESTART (0x0200) /* Restart PHY auto-negotiation */
#define PHY_FULL_DUPLEX (0x0100) /* Force PHY in full duplex mode */
#define PHY_HP_MDIX (0x0020) /* Set PHY in HP auto MDI-X mode */
#define PHY_FORCE_MDIX (0x0010) /* Force MDI-X */
#define PHY_AUTO_MDIX_DISABLE (0x0008) /* Disable auto MDI-X */
#define PHY_TRANSMIT_DISABLE (0x0002) /* Disable PHY transmit */
#define PHY_LED_DISABLE (0x0001) /* Disable PHY LED */
#define REG_PHY_STATUS (0xE6) /* P1MBSR */
#define PHY_100BT4_CAPABLE (0x8000) /* 100 BASE-T4 capable */
#define PHY_100BTX_FD_CAPABLE (0x4000) /* 100BASE-TX full duplex capable */
#define PHY_100BTX_CAPABLE (0x2000) /* 100BASE-TX half duplex capable */
#define PHY_10BT_FD_CAPABLE (0x1000) /* 10BASE-TX full duplex capable */
#define PHY_10BT_CAPABLE (0x0800) /* 10BASE-TX half duplex capable */
#define PHY_AUTO_NEG_ACKNOWLEDGE (0x0020) /* Auto-negotiation complete */
#define PHY_AUTO_NEG_CAPABLE (0x0008) /* Auto-negotiation capable */
#define PHY_LINK_UP (0x0004) /* PHY link is up */
#define PHY_EXTENDED_CAPABILITY (0x0001) /* PHY extended register capable */
#define REG_PHY_ID_LOW (0xE8) /* PHY1ILR */
#define REG_PHY_ID_HIGH (0xEA) /* PHY1IHR */
#define REG_PHY_AUTO_NEGOTIATION (0xEC) /* P1ANAR */
#define PHY_AUTO_NEG_SYM_PAUSE (0x0400) /* Advertise pause capability */
#define PHY_AUTO_NEG_100BTX_FD (0x0100) /* Advertise 100 full-duplex capability */
#define PHY_AUTO_NEG_100BTX (0x0080) /* Advertise 100 half-duplex capability */
#define PHY_AUTO_NEG_10BT_FD (0x0040) /* Advertise 10 full-duplex capability */
#define PHY_AUTO_NEG_10BT (0x0020) /* Advertise 10 half-duplex capability */
#define PHY_AUTO_NEG_SELECTOR (0x001F) /* Selector field mask */
#define PHY_AUTO_NEG_802_3 (0x0001) /* 802.3 */
#define REG_PHY_REMOTE_CAPABILITY (0xEE) /* P1ANLPR */
#define PHY_REMOTE_SYM_PAUSE (0x0400) /* Link partner pause capability */
#define PHY_REMOTE_100BTX_FD (0x0100) /* Link partner 100 full-duplex capability */
#define PHY_REMOTE_100BTX (0x0080) /* Link partner 100 half-duplex capability */
#define PHY_REMOTE_10BT_FD (0x0040) /* Link partner 10 full-duplex capability */
#define PHY_REMOTE_10BT (0x0020) /* Link partner 10 half-duplex capability */
#define REG_PORT_LINK_MD (0xF4) /* P1SCLMD */
#define PORT_CABLE_10M_SHORT (0x8000) /* Cable length is less than 10m short */
#define PORT_CABLE_STAT_FAILED (0x6000) /* Cable diagnostic test fail */
#define PORT_CABLE_STAT_SHORT (0x4000) /* Short condition detected in the cable */
#define PORT_CABLE_STAT_OPEN (0x2000) /* Open condition detected in the cable */
#define PORT_CABLE_STAT_NORMAL (0x0000) /* Normal condition */
#define PORT_CABLE_DIAG_RESULT (0x6000) /* Cable diagnostic test result mask */
#define PORT_START_CABLE_DIAG (0x1000) /* Enable cable diagnostic test */
#define PORT_FORCE_LINK (0x0800) /* Enable force link pass */
#define PORT_POWER_SAVING (0x0400) /* Disable power saving */
#define PORT_REMOTE_LOOPBACK (0x0200) /* Enable remote loopback at PHY */
#define PORT_CABLE_FAULT_COUNTER (0x01FF) /* Cable length distance to the fault */
#define REG_PORT_CTRL (0xF6) /* P1CR */
#define PORT_LED_OFF (0x8000) /* Turn off all the port LEDs (LED3/LED2/LED1/LED0) */
#define PORT_TX_DISABLE (0x4000) /* Disable port transmit */
#define PORT_AUTO_NEG_RESTART (0x2000) /* Restart auto-negotiation */
#define PORT_POWER_DOWN (0x0800) /* Set port power-down */
#define PORT_AUTO_MDIX_DISABLE (0x0400) /* Disable auto MDI-X */
#define PORT_FORCE_MDIX (0x0200) /* Force MDI-X */
#define PORT_AUTO_NEG_ENABLE (0x0080) /* Enable auto-negotiation */
#define PORT_FORCE_100_MBIT (0x0040) /* Force PHY 100Mbps */
#define PORT_FORCE_FULL_DUPLEX (0x0020) /* Force PHY in full duplex mode */
#define PORT_AUTO_NEG_SYM_PAUSE (0x0010) /* Advertise pause capability */
#define PORT_AUTO_NEG_100BTX_FD (0x0008) /* Advertise 100 full-duplex capability */
#define PORT_AUTO_NEG_100BTX (0x0004) /* Advertise 100 half-duplex capability */
#define PORT_AUTO_NEG_10BT_FD (0x0002) /* Advertise 10 full-duplex capability */
#define PORT_AUTO_NEG_10BT (0x0001) /* Advertise 10 half-duplex capability */
#define REG_PORT_STATUS (0xF8) /* P1SR */
#define PORT_HP_MDIX (0x8000) /* Set PHY in HP auto MDI-X mode */
#define PORT_REVERSED_POLARITY (0x2000) /* Polarity is reversed */
#define PORT_RX_FLOW_CTRL (0x1000) /* Reeive flow control feature is active */
#define PORT_TX_FLOW_CTRL (0x0800) /* Transmit flow control feature is active */
#define PORT_STAT_SPEED_100MBIT (0x0400) /* Link is 100Mbps */
#define PORT_STAT_FULL_DUPLEX (0x0200) /* Link is full duplex mode */
#define PORT_MDIX_STATUS (0x0080) /* Is MDI */
#define PORT_AUTO_NEG_COMPLETE (0x0040) /* Auto-negotiation complete */
#define PORT_STATUS_LINK_GOOD (0x0020) /* PHY link is up */
#define PORT_REMOTE_SYM_PAUSE (0x0010) /* Link partner pause capability */
#define PORT_REMOTE_100BTX_FD (0x0008) /* Link partner 100 full-duplex capability */
#define PORT_REMOTE_100BTX (0x0004) /* Link partner 100 half-duplex capability */
#define PORT_REMOTE_10BT_FD (0x0002) /* Link partner 10 full-duplex capability */
#define PORT_REMOTE_10BT (0x0001) /* Link partner 10 half-duplex capability */
#endif /* KSZ8851SNL_REG_H_INCLUDED */

View file

@ -1,217 +1,217 @@
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "wifi-decl.h"
#include "wmerrno.h"
#include "wifi.h"
#include <wmlog.h>
#define net_e(...) \
wmlog_e("freertos_tcp", ##__VA_ARGS__)
#define net_w(...) \
wmlog_w("freertos_tcp", ##__VA_ARGS__)
#define net_d(...) \
wmlog("freertos_tcp", ##__VA_ARGS__)
#if 0 //this is lwip structure.
#define MAX_INTERFACES_SUPPORTED 3
static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];
#endif
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
/** 255.255.255.255 */
#define IPADDR_NONE ((u32_t)0xffffffffUL)
/** 127.0.0.1 */
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
/** 0.0.0.0 */
#define IPADDR_ANY ((u32_t)0x00000000UL)
/** 255.255.255.255 */
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
/** 255.255.255.255 */
#define INADDR_NONE IPADDR_NONE
/** 127.0.0.1 */
#define INADDR_LOOPBACK IPADDR_LOOPBACK
/** 0.0.0.0 */
#define INADDR_ANY IPADDR_ANY
/** 255.255.255.255 */
#define INADDR_BROADCAST IPADDR_BROADCAST
enum if_state_t {
INTERFACE_DOWN = 0,
INTERFACE_UP,
};
struct ip_addr {
u32_t addr;
};
#define MLAN_BSS_TYPE_STA 0
extern uint8_t outbuf[2048];
extern bool mlan_is_amsdu(const t_u8 *rcvdata);
extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);
extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);
extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer);
static volatile uint32_t xInterfaceState = INTERFACE_DOWN;
static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)
{
int interface = BSS_TYPE_STA;
t_u8 *payload = NULL;
t_u16 payload_len = 0;
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);
if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {
net_d("Dropping packet\r\n");
return WM_SUCCESS;
}
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = payload_len;
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return WM_FAIL;
}
}
return WM_SUCCESS;
}
/* Callback function called from the wifi module */
void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,
const t_u16 datalen)
{
if (interface == BSS_TYPE_STA)
process_data_packet(rcvdata, datalen);
}
BaseType_t xNetworkInterfaceInitialise( void )
{
uint8_t ret;
mac_addr_t mac_addr;
ret = wifi_get_device_mac_addr(&mac_addr);
if (ret != WM_SUCCESS) {
net_d("Failed to get mac address");
}
FreeRTOS_UpdateMACAddress(mac_addr.mac);
return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
/* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
/* FIX ME. */
return pdFALSE;
}
void vNetworkNotifyIFDown()
{
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
xInterfaceState = INTERFACE_DOWN;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {
/* Could not send the message, so it is still pending. */
net_e("Could not send network down event");
}
else {
/* Message was sent so it is not pending. */
net_d("Sent network down event");
}
}
void vNetworkNotifyIFUp()
{
xInterfaceState = INTERFACE_UP;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
uint8_t pkt_len;
if (pxNetworkBuffer == NULL ||
pxNetworkBuffer->pucEthernetBuffer == NULL ||
pxNetworkBuffer->xDataLength == 0) {
net_d("Incorrect params");
return pdFALSE;
}
memset(outbuf, 0x00, sizeof(outbuf));
pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */
memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,
pxNetworkBuffer->xDataLength);
int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);
if (ret != WM_SUCCESS) {
net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
}
if (xReleaseAfterSend != pdFALSE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return ret == WM_SUCCESS ? pdTRUE : pdFALSE;
}
/*
FreeRTOS+TCP V2.0.11
Copyright (C) 2018 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
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
http://aws.amazon.com/freertos
http://www.FreeRTOS.org
*/
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "list.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
#include "wifi-decl.h"
#include "wmerrno.h"
#include "wifi.h"
#include <wmlog.h>
#define net_e(...) \
wmlog_e("freertos_tcp", ##__VA_ARGS__)
#define net_w(...) \
wmlog_w("freertos_tcp", ##__VA_ARGS__)
#define net_d(...) \
wmlog("freertos_tcp", ##__VA_ARGS__)
#if 0 //this is lwip structure.
#define MAX_INTERFACES_SUPPORTED 3
static struct netif *netif_arr[MAX_INTERFACES_SUPPORTED];
#endif
/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
driver will filter incoming packets and only pass the stack those packets it
considers need processing. */
#if( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 )
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
#else
#define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
#endif
#define IP_ADDR_ANY ((ip_addr_t *)&ip_addr_any)
#define IP_ADDR_BROADCAST ((ip_addr_t *)&ip_addr_broadcast)
/** 255.255.255.255 */
#define IPADDR_NONE ((u32_t)0xffffffffUL)
/** 127.0.0.1 */
#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL)
/** 0.0.0.0 */
#define IPADDR_ANY ((u32_t)0x00000000UL)
/** 255.255.255.255 */
#define IPADDR_BROADCAST ((u32_t)0xffffffffUL)
/** 255.255.255.255 */
#define INADDR_NONE IPADDR_NONE
/** 127.0.0.1 */
#define INADDR_LOOPBACK IPADDR_LOOPBACK
/** 0.0.0.0 */
#define INADDR_ANY IPADDR_ANY
/** 255.255.255.255 */
#define INADDR_BROADCAST IPADDR_BROADCAST
enum if_state_t {
INTERFACE_DOWN = 0,
INTERFACE_UP,
};
struct ip_addr {
u32_t addr;
};
#define MLAN_BSS_TYPE_STA 0
extern uint8_t outbuf[2048];
extern bool mlan_is_amsdu(const t_u8 *rcvdata);
extern t_u8 *mlan_get_payload(const t_u8 *rcvdata, t_u16 *payload_len, int *interface);
extern int wrapper_wlan_handle_amsdu_rx_packet(const t_u8 *rcvdata, const t_u16 datalen);
extern int wrapper_wlan_handle_rx_packet(const t_u16 datalen, const t_u8 *rcvdata, NetworkBufferDescriptor_t *pxNetworkBuffer);
static volatile uint32_t xInterfaceState = INTERFACE_DOWN;
static int process_data_packet(const t_u8 *databuf, const t_u16 datalen)
{
int interface = BSS_TYPE_STA;
t_u8 *payload = NULL;
t_u16 payload_len = 0;
const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
NetworkBufferDescriptor_t *pxNetworkBuffer;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
payload = (t_u8 *)mlan_get_payload(databuf, &payload_len, &interface);
if( eConsiderFrameForProcessing( payload ) != eProcessBuffer ) {
net_d("Dropping packet\r\n");
return WM_SUCCESS;
}
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor(/*payload_len*/datalen, xDescriptorWaitTime);
if (pxNetworkBuffer != NULL) {
/* Set the packet size, in case a larger buffer was returned. */
pxNetworkBuffer->xDataLength = payload_len;
/* Copy the packet data. */
memcpy(pxNetworkBuffer->pucEthernetBuffer, payload, payload_len);
xRxEvent.pvData = (void *) pxNetworkBuffer;
if ( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime) == pdFAIL ) {
wmprintf("Failed to enqueue packet to network stack %p, len %d", payload, payload_len);
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
return WM_FAIL;
}
}
return WM_SUCCESS;
}
/* Callback function called from the wifi module */
void handle_data_packet(const t_u8 interface, const t_u8 *rcvdata,
const t_u16 datalen)
{
if (interface == BSS_TYPE_STA)
process_data_packet(rcvdata, datalen);
}
BaseType_t xNetworkInterfaceInitialise( void )
{
uint8_t ret;
mac_addr_t mac_addr;
ret = wifi_get_device_mac_addr(&mac_addr);
if (ret != WM_SUCCESS) {
net_d("Failed to get mac address");
}
FreeRTOS_UpdateMACAddress(mac_addr.mac);
return ( xInterfaceState == INTERFACE_UP && ret == WM_SUCCESS ) ? pdTRUE : pdFALSE;
}
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
/* FIX ME. */
}
BaseType_t xGetPhyLinkStatus( void )
{
/* FIX ME. */
return pdFALSE;
}
void vNetworkNotifyIFDown()
{
IPStackEvent_t xRxEvent = { eNetworkDownEvent, NULL };
xInterfaceState = INTERFACE_DOWN;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) != pdPASS ) {
/* Could not send the message, so it is still pending. */
net_e("Could not send network down event");
}
else {
/* Message was sent so it is not pending. */
net_d("Sent network down event");
}
}
void vNetworkNotifyIFUp()
{
xInterfaceState = INTERFACE_UP;
}
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t *const pxNetworkBuffer, BaseType_t xReleaseAfterSend )
{
uint8_t pkt_len;
if (pxNetworkBuffer == NULL ||
pxNetworkBuffer->pucEthernetBuffer == NULL ||
pxNetworkBuffer->xDataLength == 0) {
net_d("Incorrect params");
return pdFALSE;
}
memset(outbuf, 0x00, sizeof(outbuf));
pkt_len = 22 + 4; /* sizeof(TxPD) + INTF_HEADER_LEN */
memcpy((u8_t *) outbuf + pkt_len, (u8_t *) pxNetworkBuffer->pucEthernetBuffer,
pxNetworkBuffer->xDataLength);
int ret = wifi_low_level_output(BSS_TYPE_STA, outbuf + pkt_len, pxNetworkBuffer->xDataLength);
if (ret != WM_SUCCESS) {
net_e("Failed output %p, length %d, error %d \r\n", pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength, ret);
}
if (xReleaseAfterSend != pdFALSE) {
vReleaseNetworkBufferAndDescriptor(pxNetworkBuffer);
}
return ret == WM_SUCCESS ? pdTRUE : pdFALSE;
}

View file

@ -1,192 +1,192 @@
/*******************************************************************************
* Network Interface file
*
* Summary:
* Network Interface file for FreeRTOS-Plus-TCP stack
*
* Description:
* - Interfaces PIC32 to the FreeRTOS TCP/IP stack
*******************************************************************************/
/*******************************************************************************
* File Name: pic32_NetworkInterface.c
* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
*
* 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
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*******************************************************************************/
#ifndef PIC32_USE_ETHERNET
#include <sys/kmem.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "event_groups.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "peripheral/eth/plib_eth.h"
#include "system_config.h"
#include "system/console/sys_console.h"
#include "system/debug/sys_debug.h"
#include "system/command/sys_command.h"
#include "driver/ethmac/drv_ethmac.h"
#include "driver/miim/drv_miim.h"
#include "m2m_types.h"
#include "tcpip/tcpip.h"
#include "tcpip/src/tcpip_private.h"
#include "tcpip/src/link_list.h"
#include "wilc1000_task.h"
#include "NetworkConfig.h"
#include "iot_wifi.h"
/* local definitions and data */
/* FreeRTOS implementation functions */
BaseType_t xNetworkInterfaceInitialise( void )
{
WIFINetworkParams_t xNetworkParams;
xNetworkParams.pcSSID = clientcredentialWIFI_SSID;
xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );
xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;
xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );
xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;
xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */
/*Turn WiFi ON */
if( WIFI_On() != eWiFiSuccess )
{
return pdFAIL;
}
/* Connect to the AP */
if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )
{
return pdFAIL;
}
return pdPASS;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend )
{
BaseType_t retRes = pdFALSE;
if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
{
/* There you go */
if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )
{
retRes = pdTRUE;
}
/* The buffer has been sent so can be released. */
if( xReleaseAfterSend != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
}
return retRes;
}
/************************************* Section: helper functions ************************************************** */
/* */
/************************************* Section: worker code ************************************************** */
/* */
void xNetworkFrameReceived( uint32_t len,
uint8_t const * const frame )
{
bool pktSuccess, pktLost;
NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
pktSuccess = pktLost = false;
while( true )
{
if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )
{
break;
}
/* get the network descriptor (no data buffer) to hold this packet */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );
if( pxNetworkBuffer == NULL )
{
pktLost = true;
break;
}
/* Set the actual packet length, in case a larger buffer was
returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet. */
memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );
/* Send the data to the TCP/IP stack. */
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{ /* failed */
pktLost = true;
}
else
{ /* success */
pktSuccess = true;
iptraceNETWORK_INTERFACE_RECEIVE();
}
break;
}
if( !pktSuccess )
{ /* smth went wrong; nothing sent to the */
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pucEthernetBuffer = 0;
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
if( pktLost )
{
iptraceETHERNET_RX_EVENT_LOST();
}
}
}
#endif /* #ifndef PIC32_USE_ETHERNET */
/*******************************************************************************
* Network Interface file
*
* Summary:
* Network Interface file for FreeRTOS-Plus-TCP stack
*
* Description:
* - Interfaces PIC32 to the FreeRTOS TCP/IP stack
*******************************************************************************/
/*******************************************************************************
* File Name: pic32_NetworkInterface.c
* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
*
* 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
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE
*******************************************************************************/
#ifndef PIC32_USE_ETHERNET
#include <sys/kmem.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "event_groups.h"
#include "FreeRTOS_IP.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkInterface.h"
#include "NetworkBufferManagement.h"
#include "peripheral/eth/plib_eth.h"
#include "system_config.h"
#include "system/console/sys_console.h"
#include "system/debug/sys_debug.h"
#include "system/command/sys_command.h"
#include "driver/ethmac/drv_ethmac.h"
#include "driver/miim/drv_miim.h"
#include "m2m_types.h"
#include "tcpip/tcpip.h"
#include "tcpip/src/tcpip_private.h"
#include "tcpip/src/link_list.h"
#include "wilc1000_task.h"
#include "NetworkConfig.h"
#include "iot_wifi.h"
/* local definitions and data */
/* FreeRTOS implementation functions */
BaseType_t xNetworkInterfaceInitialise( void )
{
WIFINetworkParams_t xNetworkParams;
xNetworkParams.pcSSID = clientcredentialWIFI_SSID;
xNetworkParams.ucSSIDLength = sizeof( clientcredentialWIFI_SSID );
xNetworkParams.pcPassword = clientcredentialWIFI_PASSWORD;
xNetworkParams.ucPasswordLength = sizeof( clientcredentialWIFI_PASSWORD );
xNetworkParams.xSecurity = clientcredentialWIFI_SECURITY;
xNetworkParams.cChannel = M2M_WIFI_CH_ALL; /* Scan all channels (255) */
/*Turn WiFi ON */
if( WIFI_On() != eWiFiSuccess )
{
return pdFAIL;
}
/* Connect to the AP */
if( WIFI_ConnectAP( &xNetworkParams ) != eWiFiSuccess )
{
return pdFAIL;
}
return pdPASS;
}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t xReleaseAfterSend )
{
BaseType_t retRes = pdFALSE;
if( ( pxDescriptor != 0 ) && ( pxDescriptor->pucEthernetBuffer != 0 ) && ( pxDescriptor->xDataLength != 0 ) )
{
/* There you go */
if( WDRV_EXT_DataSend( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ) == 0 )
{
retRes = pdTRUE;
}
/* The buffer has been sent so can be released. */
if( xReleaseAfterSend != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
}
return retRes;
}
/************************************* Section: helper functions ************************************************** */
/* */
/************************************* Section: worker code ************************************************** */
/* */
void xNetworkFrameReceived( uint32_t len,
uint8_t const * const frame )
{
bool pktSuccess, pktLost;
NetworkBufferDescriptor_t * pxNetworkBuffer = NULL;
IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
pktSuccess = pktLost = false;
while( true )
{
if( eConsiderFrameForProcessing( frame ) != eProcessBuffer )
{
break;
}
/* get the network descriptor (no data buffer) to hold this packet */
pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( len, 0 );
if( pxNetworkBuffer == NULL )
{
pktLost = true;
break;
}
/* Set the actual packet length, in case a larger buffer was
returned. */
pxNetworkBuffer->xDataLength = len;
/* Copy the packet. */
memcpy( pxNetworkBuffer->pucEthernetBuffer, frame, len );
/* Send the data to the TCP/IP stack. */
xRxEvent.pvData = ( void * ) pxNetworkBuffer;
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{ /* failed */
pktLost = true;
}
else
{ /* success */
pktSuccess = true;
iptraceNETWORK_INTERFACE_RECEIVE();
}
break;
}
if( !pktSuccess )
{ /* smth went wrong; nothing sent to the */
if( pxNetworkBuffer != NULL )
{
pxNetworkBuffer->pucEthernetBuffer = 0;
vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
}
if( pktLost )
{
iptraceETHERNET_RX_EVENT_LOST();
}
}
}
#endif /* #ifndef PIC32_USE_ETHERNET */