summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
diff options
context:
space:
mode:
Diffstat (limited to 'FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c')
-rw-r--r--FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c1061
1 files changed, 464 insertions, 597 deletions
diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
index b9278c042..84019d637 100644
--- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
+++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/STM32Fxx/NetworkInterface.c
@@ -44,26 +44,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "FreeRTOS_DNS.h"
+#include "FreeRTOS_ARP.h"
#include "NetworkBufferManagement.h"
#include "NetworkInterface.h"
+#include "phyHandling.h"
/* ST includes. */
-#include "stm32f4xx_hal.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
+#if defined( STM32F7xx )
+ #include "stm32f7xx_hal.h"
+#elif defined( STM32F4xx )
+ #include "stm32f4xx_hal.h"
+#elif defined( STM32F2xx )
+ #include "stm32f2xx_hal.h"
+#elif !defined( _lint ) /* Lint does not like an #error */
+ #error What part?
#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
+#include "stm32fxx_hal_eth.h"
/* Interrupt events to process. Currently only the Rx event is processed
although code for other events is included to allow for possible future
@@ -78,77 +75,19 @@ expansion. */
ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \
ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )
-/* Naming and numbering of PHY registers. */
-#define PHY_REG_00_BMCR 0x00 /* Basic Mode Control Register */
-#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_ID_LAN8720 0x0007c0f0
-#define PHY_ID_DP83848I 0x20005C90
-
-#ifndef USE_STM324xG_EVAL
- #define USE_STM324xG_EVAL 1
+#ifndef niEMAC_HANDLER_TASK_PRIORITY
+ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1
#endif
-#if( USE_STM324xG_EVAL == 0 )
- #define EXPECTED_PHY_ID PHY_ID_LAN8720
- #define PHY_REG_1F_PHYSPCS 0x1F /* 31 RW PHY Special Control Status */
- /* Use 3 bits in register 31 */
- #define PHYSPCS_SPEED_MASK 0x0C
- #define PHYSPCS_SPEED_10 0x04
- #define PHYSPCS_SPEED_100 0x08
- #define PHYSPCS_FULL_DUPLEX 0x10
-#else
- #define EXPECTED_PHY_ID PHY_ID_DP83848I
+#define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
- #define PHY_REG_10_PHY_SR 0x10 /* PHY status register Offset */
- #define PHY_REG_19_PHYCR 0x19 /* 25 RW PHY Control Register */
+#if( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )
+ #warning Consider enabling checksum offloading
#endif
-/* Some defines used internally here to indicate preferences about speed, MDIX
-(wired direct or crossed), and duplex (half or full). */
-#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)
-
-#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020) /*!< Auto-Negotiation process completed */
-
-/*
- * Description of all capabilities that can be advertised to
- * the peer (usually a switch or router).
- */
-#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_ALL ( ADVERTISE_10HALF | ADVERTISE_10FULL | \
- ADVERTISE_100HALF | ADVERTISE_100FULL)
-
-/*
- * Value for the 'PHY_REG_00_BMCR', the PHY's Basic Mode Control Register
- */
-#define BMCR_FULLDPLX 0x0100 /* Full duplex. */
-#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart. */
-#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation. */
-#define BMCR_SPEED100 0x2000 /* Select 100Mbps. */
-#define BMCR_RESET 0x8000 /* Reset the PHY. */
-
-#define PHYCR_MDIX_EN 0x8000 /* Enable Auto MDIX. */
-#define PHYCR_MDIX_FORCE 0x4000 /* Force MDIX crossed. */
-
-#define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */
+#ifndef niDESCRIPTOR_WAIT_TIME_MS
+ #define niDESCRIPTOR_WAIT_TIME_MS 250uL
+#endif
/*
* Most users will want a PHY that negotiates about
@@ -191,6 +130,31 @@ FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */
#define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE )
#endif
+/* Two choices must be made: RMII versus MII,
+and the index of the PHY in use ( between 0 and 31 ). */
+#ifndef ipconfigUSE_RMII
+ #ifdef STM32F7xx
+ #define ipconfigUSE_RMII 1
+ #else
+ #define ipconfigUSE_RMII 0
+ #endif /* STM32F7xx */
+#endif /* ipconfigUSE_RMII */
+
+#if( ipconfigUSE_RMII != 0 )
+ #warning Using RMII, make sure if this is correct
+#else
+ #warning Using MII, make sure if this is correct
+#endif
+
+typedef enum
+{
+ eMACInit, /* Must initialise MAC. */
+ eMACPass, /* Initialisation was successful. */
+ eMACFailed, /* Initialisation failed. */
+} eMAC_INIT_STATUS_TYPE;
+
+static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit;
+
/*-----------------------------------------------------------*/
/*
@@ -231,43 +195,30 @@ static void prvDMATxDescListInit( void );
*/
static void prvDMARxDescListInit( void );
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- /* After packets have been sent, the network
- buffers will be released. */
- static void vClearTXBuffers( void );
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+/* After packets have been sent, the network
+buffers will be released. */
+static void vClearTXBuffers( void );
/*-----------------------------------------------------------*/
-typedef struct _PhyProperties_t
-{
- uint8_t speed;
- uint8_t mdix;
- uint8_t duplex;
- uint8_t spare;
-} PhyProperties_t;
-
/* Bit map of outstanding ETH interrupt events for processing. Currently only
the Rx interrupt is handled, although code is included for other events to
enable future expansion. */
static volatile uint32_t ulISREvents;
-/* 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
+static EthernetPhy_t xPhyObject;
+
/* Ethernet handle. */
static ETH_HandleTypeDef xETH;
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- /* xTXDescriptorSemaphore is a counting semaphore with
- a maximum count of ETH_TXBUFNB, which is the number of
- DMA TX descriptors. */
- static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+/* xTXDescriptorSemaphore is a counting semaphore with
+a maximum count of ETH_TXBUFNB, which is the number of
+DMA TX descriptors. */
+static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;
/*
* Note: it is adviced to define both
@@ -282,30 +233,39 @@ static ETH_HandleTypeDef xETH;
* TX buffers are allocated in a zero-copy driver.
*/
/* MAC buffers: ---------------------------------------------------------*/
-__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ] __ALIGN_END;/* Ethernet Rx MA Descriptor */
-#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
- __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; /* Ethernet Receive Buffer */
-#endif
-__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ] __ALIGN_END;/* Ethernet Tx DMA Descriptor */
-#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
- __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; /* Ethernet Transmit Buffer */
+/* Put the DMA descriptors in '.first_data'.
+This is important for STM32F7, which has an L1 data cache.
+The first 64KB of the SRAM is not cached.
+See README.TXT in this folder. */
+
+/* Ethernet Rx MA Descriptor */
+__attribute__ ((aligned (32)))
+#if defined(STM32F7xx)
+ __attribute__ ((section(".first_data")))
#endif
+ ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ];
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- /* DMATxDescToClear points to the next TX DMA descriptor
- that must be cleared by vClearTXBuffers(). */
- static __IO ETH_DMADescTypeDef *DMATxDescToClear;
+#if( ipconfigZERO_COPY_RX_DRIVER == 0 )
+ /* Ethernet Receive Buffer */
+ __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END;
#endif
-/* Value to be written into the 'Basic mode Control Register'. */
-static uint32_t ulBCRvalue;
+/* Ethernet Tx DMA Descriptor */
+__attribute__ ((aligned (32)))
+#if defined(STM32F7xx)
+ __attribute__ ((section(".first_data")))
+#endif
+ ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ];
-/* Value to be written into the 'Advertisement Control Register'. */
-static uint32_t ulACRValue;
+#if( ipconfigZERO_COPY_TX_DRIVER == 0 )
+ /* Ethernet Transmit Buffer */
+ __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END;
+#endif
-/* ucMACAddress as it appears in main.c */
-extern const uint8_t ucMACAddress[ 6 ];
+/* DMATxDescToClear points to the next TX DMA descriptor
+that must be cleared by vClearTXBuffers(). */
+static __IO ETH_DMADescTypeDef *DMATxDescToClear;
/* 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
@@ -316,28 +276,28 @@ static TaskHandle_t xEMACTaskHandle = NULL;
const PhyProperties_t xPHYProperties =
{
#if( ipconfigETHERNET_AN_ENABLE != 0 )
- .speed = PHY_SPEED_AUTO,
- .duplex = PHY_DUPLEX_AUTO,
+ .ucSpeed = PHY_SPEED_AUTO,
+ .ucDuplex = PHY_DUPLEX_AUTO,
#else
#if( ipconfigETHERNET_USE_100MB != 0 )
- .speed = PHY_SPEED_100,
+ .ucSpeed = PHY_SPEED_100,
#else
- .speed = PHY_SPEED_10,
+ .ucSpeed = PHY_SPEED_10,
#endif
#if( ipconfigETHERNET_USE_FULL_DUPLEX != 0 )
- .duplex = PHY_DUPLEX_FULL,
+ .ucDuplex = PHY_DUPLEX_FULL,
#else
- .duplex = PHY_DUPLEX_HALF,
+ .ucDuplex = PHY_DUPLEX_HALF,
#endif
#endif
#if( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 )
- .mdix = PHY_MDIX_AUTO,
+ .ucMDI_X = PHY_MDIX_AUTO,
#elif( ipconfigETHERNET_CROSSED_LINK != 0 )
- .mdix = PHY_MDIX_CROSSED,
+ .ucMDI_X = PHY_MDIX_CROSSED,
#else
- .mdix = PHY_MDIX_DIRECT,
+ .ucMDI_X = PHY_MDIX_DIRECT,
#endif
};
@@ -347,6 +307,8 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef *heth )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+ ( void ) heth;
+
/* Ethernet RX-Complete callback function, elsewhere declared as weak. */
ulISREvents |= EMAC_IF_RX_EVENT;
/* Wakeup the prvEMACHandlerTask. */
@@ -358,46 +320,46 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
}
/*-----------------------------------------------------------*/
-#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
- {
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
-
- /* This call-back is only useful in case packets are being sent
- zero-copy. Once they're sent, the buffers will be released
- by the function vClearTXBuffers(). */
- ulISREvents |= EMAC_IF_TX_EVENT;
- /* Wakeup the prvEMACHandlerTask. */
- if( xEMACTaskHandle != NULL )
- {
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
- }
+void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )
+{
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- }
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+ ( void ) heth;
+ /* This call-back is only useful in case packets are being sent
+ zero-copy. Once they're sent, the buffers will be released
+ by the function vClearTXBuffers(). */
+ ulISREvents |= EMAC_IF_TX_EVENT;
+ /* Wakeup the prvEMACHandlerTask. */
+ if( xEMACTaskHandle != NULL )
+ {
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
+ }
+}
/*-----------------------------------------------------------*/
+static void vClearTXBuffers()
+{
+__IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;
+size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- static void vClearTXBuffers()
- {
- __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;
NetworkBufferDescriptor_t *pxNetworkBuffer;
uint8_t *ucPayLoad;
- size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );
+#endif
- /* This function is called after a TX-completion interrupt.
- It will release each Network Buffer used in xNetworkInterfaceOutput().
- 'uxCount' represents the number of descriptors given to DMA for transmission.
- After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
- while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
+ /* This function is called after a TX-completion interrupt.
+ It will release each Network Buffer used in xNetworkInterfaceOutput().
+ 'uxCount' represents the number of descriptors given to DMA for transmission.
+ After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */
+ while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )
+ {
+ if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
+ {
+ break;
+ }
+ #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
{
- if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )
- {
- break;
- }
-
ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;
if( ucPayLoad != NULL )
@@ -409,15 +371,16 @@ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
}
DMATxDescToClear->Buffer1Addr = ( uint32_t )0u;
}
+ }
+ #endif /* ipconfigZERO_COPY_TX_DRIVER */
- DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
+ DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );
- uxCount--;
- /* Tell the counting semaphore that one more TX descriptor is available. */
- xSemaphoreGive( xTXDescriptorSemaphore );
- }
+ uxCount--;
+ /* Tell the counting semaphore that one more TX descriptor is available. */
+ xSemaphoreGive( xTXDescriptorSemaphore );
}
-#endif /* ipconfigZERO_COPY_TX_DRIVER */
+}
/*-----------------------------------------------------------*/
BaseType_t xNetworkInterfaceInitialise( void )
@@ -425,90 +388,117 @@ BaseType_t xNetworkInterfaceInitialise( void )
HAL_StatusTypeDef hal_eth_init_status;
BaseType_t xResult;
- if( xEMACTaskHandle == NULL )
+ if( xMacInitStatus == eMACInit )
{
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
+ if( xTXDescriptorSemaphore == NULL )
{
- if( xTXDescriptorSemaphore == NULL )
- {
- xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );
- configASSERT( xTXDescriptorSemaphore );
- }
+ xMacInitStatus = eMACFailed;
}
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
+ else
+ {
+ /* Initialise ETH */
- /* Initialise ETH */
+ xETH.Instance = ETH;
+ xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
+ xETH.Init.Speed = ETH_SPEED_100M;
+ xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+ /* Value of PhyAddress doesn't matter, will be probed for. */
+ xETH.Init.PhyAddress = 0;
- xETH.Instance = ETH;
- xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
- xETH.Init.Speed = ETH_SPEED_100M;
- xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
- xETH.Init.PhyAddress = 1;
+ xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress();
+ xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
- xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;
- xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+ {
+ /* using the ETH_CHECKSUM_BY_HARDWARE option:
+ both the IP and the protocol checksums will be calculated
+ by the peripheral. */
+ xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+ }
+ #else
+ {
+ xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
+ }
+ #endif
- /* using the ETH_CHECKSUM_BY_HARDWARE option:
- both the IP and the protocol checksums will be calculated
- by the peripheral. */
- xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
+ #if( ipconfigUSE_RMII != 0 )
+ {
+ xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
+ }
+ #else
+ {
+ xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
+ }
+ #endif /* ipconfigUSE_RMII */
- xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;
- hal_eth_init_status = HAL_ETH_Init( &xETH );
+ hal_eth_init_status = HAL_ETH_Init( &xETH );
- /* Only for inspection by debugger. */
- ( void ) hal_eth_init_status;
+ /* Only for inspection by debugger. */
+ ( void ) hal_eth_init_status;
- /* Set the TxDesc and RxDesc pointers. */
- xETH.TxDesc = DMATxDscrTab;
- xETH.RxDesc = DMARxDscrTab;
+ /* Set the TxDesc and RxDesc pointers. */
+ xETH.TxDesc = DMATxDscrTab;
+ xETH.RxDesc = DMARxDscrTab;
- /* Make sure that all unused fields are cleared. */
- memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
- memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
+ /* Make sure that all unused fields are cleared. */
+ memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );
+ memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
/* Initialize Tx Descriptors list: Chain Mode */
DMATxDescToClear = DMATxDscrTab;
- }
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
- /* Initialise TX-descriptors. */
- prvDMATxDescListInit();
+ /* Initialise TX-descriptors. */
+ prvDMATxDescListInit();
- /* Initialise RX-descriptors. */
- prvDMARxDescListInit();
+ /* Initialise RX-descriptors. */
+ prvDMARxDescListInit();
- #if( ipconfigUSE_LLMNR != 0 )
- {
- /* Program the LLMNR address at index 1. */
- prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
- }
- #endif
+ #if( ipconfigUSE_LLMNR != 0 )
+ {
+ /* Program the LLMNR address at index 1. */
+ prvMACAddressConfig( &xETH, ETH_MAC_ADDRESS1, ( uint8_t *) xLLMNR_MACAddress );
+ }
+ #endif
- /* Force a negotiation with the Switch or Router and wait for LS. */
- prvEthernetUpdateConfig( pdTRUE );
+ /* Force a negotiation with the Switch or Router and wait for LS. */
+ prvEthernetUpdateConfig( pdTRUE );
- /* 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 );
+ /* 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. */
+ if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS )
+ {
+ /* The xTXDescriptorSemaphore and the task are created successfully. */
+ xMacInitStatus = eMACPass;
+ }
+ else
+ {
+ xMacInitStatus = eMACFailed;
+ }
+ }
} /* if( xEMACTaskHandle == NULL ) */
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+ if( xMacInitStatus != eMACPass )
{
- xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
- xResult = pdPASS;
- FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
+ /* EMAC initialisation failed, return pdFAIL. */
+ xResult = pdFAIL;
}
else
{
- /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
- and it will keep on checking the PHY and set ulPHYLinkStatus when necessary. */
- xResult = pdFAIL;
- FreeRTOS_printf( ( "Link Status still low\n" ) ) ;
+ if( xPhyObject.ulLinkStatusMask != 0uL )
+ {
+ xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS;
+ xResult = pdPASS;
+ FreeRTOS_printf( ( "Link Status is high\n" ) ) ;
+ }
+ else
+ {
+ /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running
+ and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */
+ xResult = pdFAIL;
+ }
}
/* When returning non-zero, the stack will become active and
start DHCP (in configured) */
@@ -542,6 +532,10 @@ BaseType_t xIndex;
/* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */
pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
}
+ else
+ {
+ pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL );
+ }
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
if( xIndex < ETH_TXBUFNB - 1 )
@@ -625,6 +619,8 @@ static void prvMACAddressConfig(ETH_HandleTypeDef *heth, uint32_t ulIndex, uint8
{
uint32_t ulTempReg;
+ ( void ) heth;
+
/* Calculate the selected MAC address high register. */
ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ];
@@ -647,46 +643,38 @@ __IO ETH_DMADescTypeDef *pxDmaTxDesc;
/* Do not wait too long for a free TX DMA buffer. */
const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
- #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+ /* Open a do {} while ( 0 ) loop to be able to call break. */
+ do
{
- ProtocolPacket_t *pxPacket;
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+ {
+ ProtocolPacket_t *pxPacket;
- /* If the peripheral must calculate the checksum, it wants
- the protocol checksum to have a value of zero. */
- pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
+ /* If the peripheral must calculate the checksum, it wants
+ the protocol checksum to have a value of zero. */
+ pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );
- if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )
- {
- pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
+ if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
+ {
+ pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;
+ }
}
- }
- #endif
-
- /* Open a do {} while ( 0 ) loop to be able to call break. */
- do
- {
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+ #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */
+ if( xPhyObject.ulLinkStatusMask != 0 )
{
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
+ if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
{
- if( xTXDescriptorSemaphore == NULL )
- {
- break;
- }
- if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )
- {
- /* Time-out waiting for a free TX descriptor. */
- break;
- }
+ /* Time-out waiting for a free TX descriptor. */
+ break;
}
- #endif /* ipconfigZERO_COPY_TX_DRIVER */
/* This function does the actual transmission of the packet. The packet is
contained in 'pxDescriptor' that is passed to the function. */
pxDmaTxDesc = xETH.TxDesc;
/* Is this buffer available? */
- if( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 )
+ configASSERT ( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 );
+
{
/* Is this buffer available? */
/* Get bytes in current buffer. */
@@ -701,32 +689,54 @@ const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );
{
/* Copy the bytes. */
memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize );
- pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL;
}
#else
{
+ configASSERT( bReleaseAfterSend != 0 );
+
/* Move the buffer. */
pxDmaTxDesc->Buffer1Addr = ( uint32_t )pxDescriptor->pucEthernetBuffer;
- /* Ask to set the IPv4 checksum.
- Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
- pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
/* The Network Buffer has been passed to DMA, no need to release it. */
bReleaseAfterSend = pdFALSE_UNSIGNED;
}
#endif /* ipconfigZERO_COPY_TX_DRIVER */
+ /* Ask to set the IPv4 checksum.
+ Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )
+ {
+ pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC;
+ }
+ #else
+ {
+ pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC );
+ pxDmaTxDesc->Status |= ETH_DMATXDESC_IC;
+ }
+ #endif
+
+
/* Prepare transmit descriptors to give to DMA. */
/* Set LAST and FIRST segment */
pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
/* Set frame size */
pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );
+
+ #if( NETWORK_BUFFERS_CACHED != 0 )
+ {
+ BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );
+ uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );
+ cache_clean_invalidate_by_addr( pulBuffer, xlength );
+ }
+ #endif
+
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;
/* Point to next descriptor */
xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr );
-
+ /* Ensure completion of memory access */
+ __DSB();
/* Resume DMA transmission*/
xETH.Instance->DMATPDR = 0;
iptraceNETWORK_INTERFACE_TRANSMIT();
@@ -801,20 +811,24 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP )
{
- uint16_t port = pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort;
+ uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort );
+ uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort );
- if( ( xPortHasUDPSocket( port ) == pdFALSE )
+ if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )
#if ipconfigUSE_LLMNR == 1
- && ( port != FreeRTOS_ntohs( ipLLMNR_PORT ) )
+ && ( usDestinationPort != ipLLMNR_PORT )
+ && ( usSourcePort != ipLLMNR_PORT )
#endif
#if ipconfigUSE_NBNS == 1
- && ( port != FreeRTOS_ntohs( ipNBNS_PORT ) )
+ && ( usDestinationPort != ipNBNS_PORT )
+ && ( usSourcePort != ipNBNS_PORT )
#endif
#if ipconfigUSE_DNS == 1
- && ( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort != FreeRTOS_ntohs( ipDNS_PORT ) )
+ && ( usSourcePort != ipDNS_PORT )
#endif
) {
/* Drop this packet, not for this device. */
+ FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) );
return pdFALSE;
}
}
@@ -824,20 +838,59 @@ const ProtocolPacket_t *pxProtPacket = ( const ProtocolPacket_t * )pcBuffer;
}
/*-----------------------------------------------------------*/
+static void prvPassEthMessages( NetworkBufferDescriptor_t *pxDescriptor )
+{
+IPStackEvent_t xRxEvent;
+
+ xRxEvent.eEventType = eNetworkRxEvent;
+ xRxEvent.pvData = ( void * ) pxDescriptor;
+
+ if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS )
+ {
+ /* The buffer could not be sent to the stack so must be released again.
+ This is a deferred handler taskr, not a real interrupt, so it is ok to
+ use the task level function here. */
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
+ {
+ do
+ {
+ NetworkBufferDescriptor_t *pxNext = pxDescriptor->pxNextBuffer;
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+ pxDescriptor = pxNext;
+ } while( pxDescriptor != NULL );
+ }
+ #else
+ {
+ vReleaseNetworkBufferAndDescriptor( pxDescriptor );
+ }
+ #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
+ iptraceETHERNET_RX_EVENT_LOST();
+ FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) );
+ }
+ else
+ {
+ iptraceNETWORK_INTERFACE_RECEIVE();
+ }
+}
+
static BaseType_t prvNetworkInterfaceInput( void )
{
NetworkBufferDescriptor_t *pxCurDescriptor;
NetworkBufferDescriptor_t *pxNewDescriptor = NULL;
-BaseType_t xReceivedLength, xAccepted;
+#if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
+ NetworkBufferDescriptor_t *pxFirstDescriptor = NULL;
+ NetworkBufferDescriptor_t *pxLastDescriptor = NULL;
+#endif
+BaseType_t xReceivedLength = 0;
__IO ETH_DMADescTypeDef *pxDMARxDescriptor;
-xIPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL };
-const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( 250 );
+const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS );
uint8_t *pucBuffer;
pxDMARxDescriptor = xETH.RxDesc;
- if( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN) == 0 )
+ while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u )
{
+ BaseType_t xAccepted = pdTRUE;
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4;
@@ -847,18 +900,13 @@ uint8_t *pucBuffer;
/* Chained Mode */
/* Selects the next DMA Rx descriptor list for next buffer to read */
xETH.RxDesc = ( ETH_DMADescTypeDef* )pxDMARxDescriptor->Buffer2NextDescAddr;
- }
- else
- {
- xReceivedLength = 0;
- }
- /* Obtain the size of the packet and put it into the "usReceivedLength" variable. */
- /* In order to make the code easier and faster, only packets in a single buffer
- will be accepted. This can be done by making the buffers large enough to
- hold a complete Ethernet packet (1536 bytes). */
- if( xReceivedLength > 0ul && xReceivedLength < ETH_RX_BUF_SIZE )
- {
+ /* In order to make the code easier and faster, only packets in a single buffer
+ will be accepted. This can be done by making the buffers large enough to
+ hold a complete Ethernet packet (1536 bytes).
+ Therefore, two sanity checks: */
+ configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );
+
if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )
{
/* Not an Ethernet frame-type or a checmsum error. */
@@ -904,20 +952,28 @@ uint8_t *pucBuffer;
if( xAccepted != pdFALSE )
{
pxCurDescriptor->xDataLength = xReceivedLength;
- xRxEvent.pvData = ( void * ) pxCurDescriptor;
-
- /* Pass the data to the TCP/IP task for processing. */
- if( xSendEventStructToIPTask( &xRxEvent, xDescriptorWaitTime ) == pdFALSE )
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
- /* Could not send the descriptor into the TCP/IP stack, it
- must be released. */
- vReleaseNetworkBufferAndDescriptor( pxCurDescriptor );
- iptraceETHERNET_RX_EVENT_LOST();
+ pxCurDescriptor->pxNextBuffer = NULL;
+
+ if( pxFirstDescriptor == NULL )
+ {
+ // Becomes the first message
+ pxFirstDescriptor = pxCurDescriptor;
+ }
+ else if( pxLastDescriptor != NULL )
+ {
+ // Add to the tail
+ pxLastDescriptor->pxNextBuffer = pxCurDescriptor;
+ }
+
+ pxLastDescriptor = pxCurDescriptor;
}
- else
+ #else
{
- iptraceNETWORK_INTERFACE_RECEIVE();
+ prvPassEthMessages( pxCurDescriptor );
}
+ #endif
}
/* Release descriptors to DMA */
@@ -940,6 +996,8 @@ uint8_t *pucBuffer;
pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | (uint32_t)ETH_RX_BUF_SIZE;
pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN;
+ /* Ensure completion of memory access */
+ __DSB();
/* When Rx Buffer unavailable flag is set clear it and resume
reception. */
if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 )
@@ -950,311 +1008,138 @@ uint8_t *pucBuffer;
/* Resume DMA reception. */
xETH.Instance->DMARPDR = 0;
}
+ pxDMARxDescriptor = xETH.RxDesc;
}
- return ( xReceivedLength > 0 );
-}
-/*-----------------------------------------------------------*/
-
-void vMACBProbePhy( void )
-{
-uint32_t ulConfig, ulAdvertise, ulLower, ulUpper, ulMACPhyID, ulValue;
-TimeOut_t xPhyTime;
-TickType_t xRemTime = 0;
-#if( EXPECTED_PHY_ID == PHY_ID_DP83848I )
- uint32_t ulPhyControl;
-#endif
-
- HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_03_PHYSID2, &ulLower);
- HAL_ETH_ReadPHYRegister(&xETH, PHY_REG_02_PHYSID1, &ulUpper);
-
- ulMACPhyID = ( ( ulUpper << 16 ) & 0xFFFF0000 ) | ( ulLower & 0xFFF0 );
-
- /* The expected ID for the 'LAN8720' is 0x0007c0f0. */
- /* The expected ID for the 'DP83848I' is 0x20005C90. */
-
- FreeRTOS_printf( ( "PHY ID %lX (%s)\n", ulMACPhyID,
- ( ulMACPhyID == EXPECTED_PHY_ID ) ? "OK" : "Unknown" ) );
-
- /* Remove compiler warning if FreeRTOS_printf() is not defined. */
- ( void ) ulMACPhyID;
-
- /* Set advertise register. */
- if( ( xPHYProperties.speed == PHY_SPEED_AUTO ) && ( xPHYProperties.duplex == PHY_DUPLEX_AUTO ) )
+ #if( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
{
- ulAdvertise = ADVERTISE_CSMA | ADVERTISE_ALL;
- /* Reset auto-negotiation capability. */
- }
- else
- {
- ulAdvertise = ADVERTISE_CSMA;
-
- if( xPHYProperties.speed == PHY_SPEED_AUTO )
- {
- if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
- {
- ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_100FULL;
- }
- else
- {
- ulAdvertise |= ADVERTISE_10HALF | ADVERTISE_100HALF;
- }
- }
- else if( xPHYProperties.duplex == PHY_DUPLEX_AUTO )
+ if( pxFirstDescriptor != NULL )
{
- if( xPHYProperties.speed == PHY_SPEED_10 )
- {
- ulAdvertise |= ADVERTISE_10FULL | ADVERTISE_10HALF;
- }
- else
- {
- ulAdvertise |= ADVERTISE_100FULL | ADVERTISE_100HALF;
- }
- }
- else if( xPHYProperties.speed == PHY_SPEED_100 )
- {
- if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
- {
- ulAdvertise |= ADVERTISE_100FULL;
- }
- else
- {
- ulAdvertise |= ADVERTISE_100HALF;
- }
- }
- else
- {
- if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
- {
- ulAdvertise |= ADVERTISE_10FULL;
- }
- else
- {
- ulAdvertise |= ADVERTISE_10HALF;
- }
+ prvPassEthMessages( pxFirstDescriptor );
}
}
+ #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
- /* Read Control register. */
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
-
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig | BMCR_RESET );
- xRemTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL );
- vTaskSetTimeOutState( &xPhyTime );
+ return ( xReceivedLength > 0 );
+}
+/*-----------------------------------------------------------*/
- for( ; ; )
- {
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulValue );
- if( ( ulValue & BMCR_RESET ) == 0 )
- {
- FreeRTOS_printf( ( "BMCR_RESET ready\n" ) );
- break;
- }
- if( xTaskCheckForTimeOut( &xPhyTime, &xRemTime ) != pdFALSE )
- {
- FreeRTOS_printf( ( "BMCR_RESET timed out\n" ) );
- break;
- }
- }
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulConfig & ~BMCR_RESET );
- vTaskDelay( pdMS_TO_TICKS( 50ul ) );
+BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )
+{
+uint16_t usPrevAddress = xETH.Init.PhyAddress;
+BaseType_t xResult;
+HAL_StatusTypeDef xHALResult;
- /* Write advertise register. */
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulAdvertise );
+ xETH.Init.PhyAddress = xAddress;
+ xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t )xRegister, pulValue );
+ xETH.Init.PhyAddress = usPrevAddress;
- /*
- 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. */
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_00_BMCR, &ulConfig );
-
- ulConfig &= ~( BMCR_ANRESTART | BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX );
-
- /* HT 12/9/14: always set AN-restart and AN-enable, even though the choices
- are limited. */
- ulConfig |= (BMCR_ANRESTART | BMCR_ANENABLE);
-
- if( xPHYProperties.speed == PHY_SPEED_100 )
+ if( xHALResult == HAL_OK )
{
- ulConfig |= BMCR_SPEED100;
+ xResult = 0;
}
- else if( xPHYProperties.speed == PHY_SPEED_10 )
+ else
{
- ulConfig &= ~BMCR_SPEED100;
+ xResult = -1;
}
+ return xResult;
+}
+/*-----------------------------------------------------------*/
- if( xPHYProperties.duplex == PHY_DUPLEX_FULL )
- {
- ulConfig |= BMCR_FULLDPLX;
- }
- else if( xPHYProperties.duplex == PHY_DUPLEX_HALF )
- {
- ulConfig &= ~BMCR_FULLDPLX;
- }
+BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )
+{
+uint16_t usPrevAddress = xETH.Init.PhyAddress;
+BaseType_t xResult;
+HAL_StatusTypeDef xHALResult;
+
+ xETH.Init.PhyAddress = xAddress;
+ xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t )xRegister, ulValue );
+ xETH.Init.PhyAddress = usPrevAddress;
- #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
+ if( xHALResult == HAL_OK )
{
+ xResult = 0;
}
- #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
+ else
{
- /* Read PHY Control register. */
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_19_PHYCR, &ulPhyControl );
-
- /* Clear bits which might get set: */
- ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE );
-
- if( xPHYProperties.mdix == PHY_MDIX_AUTO )
- {
- ulPhyControl |= PHYCR_MDIX_EN;
- }
- else if( xPHYProperties.mdix == 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. */
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_19_PHYCR, ulPhyControl );
+ xResult = -1;
}
- #endif
- FreeRTOS_printf( ( "+TCP: advertise: %lX config %lX\n", ulAdvertise, ulConfig ) );
+ return xResult;
+}
+/*-----------------------------------------------------------*/
- /* Now the two values to global values for later use. */
- ulBCRvalue = ulConfig;
- ulACRValue = ulAdvertise;
+void vMACBProbePhy( void )
+{
+ vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );
+ xPhyDiscover( &xPhyObject );
+ xPhyConfigure( &xPhyObject, &xPHYProperties );
}
/*-----------------------------------------------------------*/
static void prvEthernetUpdateConfig( BaseType_t xForce )
{
-__IO uint32_t ulTimeout = 0;
-uint32_t ulRegValue = 0;
-
- FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS %d Force %d\n",
- ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ,
- xForce ) );
+ FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n",
+ xPhyObject.ulLinkStatusMask,
+ ( int )xForce ) );
- if( ( xForce != pdFALSE ) || ( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) )
+ if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) )
{
/* Restart the auto-negotiation. */
if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE )
{
- /* Enable Auto-Negotiation. */
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue | BMCR_ANRESTART );
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_04_ADVERTISE, ulACRValue);
+ xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );
- /* Wait until the auto-negotiation will be completed */
- do
+ /* Configure the MAC with the Duplex Mode fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )
{
- ulTimeout++;
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue );
- } while( ( ( ulRegValue & PHY_AUTONEGO_COMPLETE) == 0 ) && ( ulTimeout < PHY_READ_TO ) );
-
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, ulBCRvalue & ~BMCR_ANRESTART );
-
- if( ulTimeout < PHY_READ_TO )
+ xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
+ }
+ else
{
- /* Reset Timeout counter. */
- ulTimeout = 0;
-
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &ulRegValue);
- if( ( ulRegValue & BMSR_LINK_STATUS ) != 0 )
- {
- ulPHYLinkStatus |= BMSR_LINK_STATUS;
- }
- else
- {
- ulPHYLinkStatus &= ~( BMSR_LINK_STATUS );
- }
-
- #if( EXPECTED_PHY_ID == PHY_ID_LAN8720 )
- {
- /* 31 RW PHY Special Control Status */
- uint32_t ulControlStatus;
-
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_1F_PHYSPCS, &ulControlStatus);
- ulRegValue = 0;
- if( ( ulControlStatus & PHYSPCS_FULL_DUPLEX ) != 0 )
- {
- ulRegValue |= PHY_DUPLEX_STATUS;
- }
- if( ( ulControlStatus & PHYSPCS_SPEED_MASK ) == PHYSPCS_SPEED_10 )
- {
- ulRegValue |= PHY_SPEED_STATUS;
- }
-
- }
- #elif( EXPECTED_PHY_ID == PHY_ID_DP83848I )
- {
- /* Read the result of the auto-negotiation. */
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_10_PHY_SR, &ulRegValue);
- }
- #endif
- FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n",
- ulRegValue,
- (ulRegValue & PHY_DUPLEX_STATUS) ? "full" : "half",
- (ulRegValue & PHY_SPEED_STATUS) ? 10 : 100,
- ((ulPHYLinkStatus |= BMSR_LINK_STATUS) != 0) ? "high" : "low" ) );
-
- /* Configure the MAC with the Duplex Mode fixed by the
- auto-negotiation process. */
- if( ( ulRegValue & PHY_DUPLEX_STATUS ) != ( uint32_t ) RESET )
- {
- /* Set Ethernet duplex mode to Full-duplex following the
- auto-negotiation. */
- xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
- }
- else
- {
- /* Set Ethernet duplex mode to Half-duplex following the
- auto-negotiation. */
- xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
- }
+ xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;
+ }
- /* Configure the MAC with the speed fixed by the
- auto-negotiation process. */
- if( ( ulRegValue & PHY_SPEED_STATUS) != 0 )
- {
- /* Set Ethernet speed to 10M following the
- auto-negotiation. */
- xETH.Init.Speed = ETH_SPEED_10M;
- }
- else
- {
- /* Set Ethernet speed to 100M following the
- auto-negotiation. */
- xETH.Init.Speed = ETH_SPEED_100M;
- }
- } /* if( ulTimeout < PHY_READ_TO ) */
+ /* Configure the MAC with the speed fixed by the
+ auto-negotiation process. */
+ if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )
+ {
+ xETH.Init.Speed = ETH_SPEED_10M;
+ }
+ else
+ {
+ xETH.Init.Speed = ETH_SPEED_100M;
+ }
}
else /* AutoNegotiation Disable */
{
- uint16_t usValue;
-
/* Check parameters */
assert_param( IS_ETH_SPEED( xETH.Init.Speed ) );
assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) );
- /* Set MAC Speed and Duplex Mode to PHY */
- usValue = ( uint16_t ) ( xETH.Init.DuplexMode >> 3 ) | ( uint16_t ) ( xETH.Init.Speed >> 1 );
- HAL_ETH_WritePHYRegister( &xETH, PHY_REG_00_BMCR, usValue );
+ if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX )
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF;
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL;
+ }
+
+ if( xETH.Init.Speed == ETH_SPEED_10M )
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10;
+ }
+ else
+ {
+ xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100;
+ }
+
+ xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO;
+
+ /* Use predefined (fixed) configuration. */
+ xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) );
}
/* ETHERNET MAC Re-Configuration */
@@ -1275,7 +1160,7 @@ BaseType_t xGetPhyLinkStatus( void )
{
BaseType_t xReturn;
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 )
+ if( xPhyObject.ulLinkStatusMask != 0 )
{
xReturn = pdPASS;
}
@@ -1288,27 +1173,43 @@ BaseType_t xReturn;
}
/*-----------------------------------------------------------*/
+/* Uncomment this in case BufferAllocation_1.c is used. */
+
+void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
+{
+static
+#if defined(STM32F7xx)
+ __attribute__ ((section(".first_data")))
+#endif
+ uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_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 += ETH_MAX_PACKET_SIZE;
+ }
+}
+/*-----------------------------------------------------------*/
+
static void prvEMACHandlerTask( void *pvParameters )
{
-TimeOut_t xPhyTime;
-TickType_t xPhyRemTime;
UBaseType_t uxLastMinBufferCount = 0;
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
UBaseType_t uxLastMinQueueSpace = 0;
#endif
UBaseType_t uxCurrentCount;
-BaseType_t xResult = 0;
-uint32_t xStatus;
+BaseType_t xResult;
const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
/* Remove compiler warnings about unused parameters. */
( void ) pvParameters;
- vTaskSetTimeOutState( &xPhyTime );
- xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS );
-
for( ;; )
{
+ xResult = 0;
uxCurrentCount = uxGetMinimumFreeNetworkBuffers();
if( uxLastMinBufferCount != uxCurrentCount )
{
@@ -1319,7 +1220,6 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) );
}
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
if( xTXDescriptorSemaphore != NULL )
{
static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1;
@@ -1332,7 +1232,7 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
}
}
- #endif
+
#if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
{
uxCurrentCount = uxGetMinimumIPQueueSpace();
@@ -1357,24 +1257,14 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
ulISREvents &= ~EMAC_IF_RX_EVENT;
xResult = prvNetworkInterfaceInput();
- if( xResult > 0 )
- {
- while( prvNetworkInterfaceInput() > 0 )
- {
- }
- }
}
if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 )
{
/* Code to release TX buffers if zero-copy is used. */
ulISREvents &= ~EMAC_IF_TX_EVENT;
- #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
- {
- /* Check if DMA packets have been delivered. */
- vClearTXBuffers();
- }
- #endif
+ /* Check if DMA packets have been delivered. */
+ vClearTXBuffers();
}
if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )
@@ -1382,34 +1272,10 @@ const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL );
/* Future extension: logging about errors that occurred. */
ulISREvents &= ~EMAC_IF_ERR_EVENT;
}
-
- if( xResult > 0 )
+ if( xPhyCheckLinkStatus( &xPhyObject, 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 )
- {
- HAL_ETH_ReadPHYRegister( &xETH, PHY_REG_01_BMSR, &xStatus );
- if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) )
- {
- ulPHYLinkStatus = xStatus;
- FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) );
- prvEthernetUpdateConfig( pdFALSE );
- }
-
- 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 );
- }
+ /* Something has changed to a Link Status, need re-check. */
+ prvEthernetUpdateConfig( pdFALSE );
}
}
}
@@ -1419,3 +1285,4 @@ void ETH_IRQHandler( void )
{
HAL_ETH_IRQHandler( &xETH );
}
+