From 6981b02a9ddb7dee76f9c89372651d51de9321ec Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 20 Mar 2023 23:04:28 -0400 Subject: [PATCH 01/68] New STM32 driver --- .../Legacy}/STM32Fxx/CMakeLists.txt | 0 .../Legacy}/STM32Fxx/NetworkInterface.c | 0 .../{ => STM32/Legacy}/STM32Fxx/readme.md | 0 .../Legacy}/STM32Fxx/stm32f2xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32f4xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32f7xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32fxx_hal_eth.c | 0 .../Legacy}/STM32Fxx/stm32fxx_hal_eth.h | 0 .../Legacy}/STM32Hxx/CMakeLists.txt | 0 .../Legacy}/STM32Hxx/NetworkInterface.c | 0 .../{ => STM32/Legacy}/STM32Hxx/readme.md | 0 .../Legacy}/STM32Hxx/stm32h7xx_hal_eth.h | 0 .../Legacy}/STM32Hxx/stm32hxx_hal_eth.c | 0 .../Legacy}/STM32Hxx/stm32hxx_hal_eth.h | 0 .../NetworkInterface/STM32/NetworkInterface.c | 684 ++++++++++++++++++ .../STM32/STM32F767ZITX_FLASH.ld | 205 ++++++ source/portable/NetworkInterface/STM32/mpu.c | 31 + 17 files changed, 920 insertions(+) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/CMakeLists.txt (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/NetworkInterface.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/readme.md (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f2xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f4xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f7xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32fxx_hal_eth.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32fxx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/CMakeLists.txt (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/NetworkInterface.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/readme.md (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32h7xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32hxx_hal_eth.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32hxx_hal_eth.h (100%) create mode 100644 source/portable/NetworkInterface/STM32/NetworkInterface.c create mode 100644 source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld create mode 100644 source/portable/NetworkInterface/STM32/mpu.c diff --git a/source/portable/NetworkInterface/STM32Fxx/CMakeLists.txt b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/CMakeLists.txt similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/CMakeLists.txt rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/CMakeLists.txt diff --git a/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/NetworkInterface.c similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/NetworkInterface.c diff --git a/source/portable/NetworkInterface/STM32Fxx/readme.md b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/readme.md similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/readme.md rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/readme.md diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f2xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f2xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f2xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f2xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f4xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f4xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f4xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f4xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f7xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f7xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f7xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.c similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.c diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Hxx/CMakeLists.txt b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/CMakeLists.txt similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/CMakeLists.txt rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/CMakeLists.txt diff --git a/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/NetworkInterface.c similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/NetworkInterface.c diff --git a/source/portable/NetworkInterface/STM32Hxx/readme.md b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/readme.md similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/readme.md rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/readme.md diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32h7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32h7xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32h7xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32h7xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.c similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.c diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c new file mode 100644 index 0000000000..a6be0dbdfe --- /dev/null +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -0,0 +1,684 @@ +/* + * Some constants, hardware definitions and comments taken from ST's HAL driver + * library, COPYRIGHT(c) 2015 STMicroelectronics. + */ + +/* + * FreeRTOS+TCP + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * 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 +#include +#include + +/* 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 "NetworkBufferManagement.h" +#include "NetworkInterface.h" +#include "phyHandling.h" + +/* ST includes. */ +#include "main.h" +#include "stm32f7xx_hal_eth.h" + +/*-----------------------------------------------------------*/ + +#define NETWORK_BUFFER_SIZE ( ( ( ETH_RX_BUF_SIZE + ipBUFFER_PADDING ) + 7 ) & ~0x7UL ) + +#define EMAC_IF_RX_EVENT 1UL +#define EMAC_IF_TX_EVENT 2UL +#define EMAC_IF_ERR_EVENT 4UL +#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT ) + +/*-----------------------------------------------------------*/ + +static BaseType_t prvNetworkInterfaceInput( void ); + +static void prvEMACHandlerTask( void * pvParameters ) __attribute__((__noreturn__)); + +static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ); + +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); + +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); + +static void prvEthernetUpdateConfig( void ); + +/*-----------------------------------------------------------*/ + +static ETH_HandleTypeDef xEthHandle; + +static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ) ) ); + +static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ) ) ); + +static ETH_TxPacketConfig xTxConfig; + +static TaskHandle_t xEMACTaskHandle; + +static SemaphoreHandle_t xTxMutex; + +static SemaphoreHandle_t xTxDescSem; + +static EthernetPhy_t xPhyObject; + +static const PhyProperties_t xPHYProperties = { + .ucSpeed = PHY_SPEED_AUTO, + .ucDuplex = PHY_DUPLEX_AUTO, + .ucMDI_X = PHY_MDIX_AUTO, +}; + +/*-----------------------------------------------------------*/ + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ NETWORK_BUFFER_SIZE ] __attribute__( ( aligned( 4 ), section( ".EthBuffersSection" ) ) ); + + for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + { + pxNetworkBuffers[ ul ].pucEthernetBuffer = &( ucNetworkPackets[ ul ][ ipBUFFER_PADDING ] ); + *( ( uint32_t * ) &( ucNetworkPackets[ ul ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ ul ] ) ); + } +} + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + BaseType_t xResult = pdFAIL; + + if( xEMACTaskHandle == NULL ) + { + static StaticSemaphore_t xTxMutexBuf; + xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + configASSERT( xTxMutex ); + vQueueAddToRegistry( xTxMutex, "TXMutex" ); + + static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); + configASSERT( xTxDescSem ); + vQueueAddToRegistry( xTxDescSem, "xTxDescSem" ); + + static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; + static StaticTask_t xEMACTaskTCB; + xEMACTaskHandle = xTaskCreateStatic( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + uxEMACTaskStack, + &xEMACTaskTCB + ); + configASSERT( xEMACTaskHandle ); + } + + if( xEthHandle.Instance == NULL ) + { + xEthHandle.Instance = ETH; + xEthHandle.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; + xEthHandle.Init.TxDesc = DMATxDscrTab; + xEthHandle.Init.RxDesc = DMARxDscrTab; + xEthHandle.Init.RxBuffLen = ETH_RX_BUF_SIZE; + + memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); + + configASSERT( HAL_ETH_Init( &xEthHandle ) == HAL_OK ); + + memset( &xTxConfig, 0, sizeof( xTxConfig ) ); + xTxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM; + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + xTxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; + + vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); + configASSERT( xPhyDiscover( &xPhyObject ) > 0 ); + configASSERT( xPhyConfigure( &xPhyObject, &xPHYProperties ) == 0 ); + configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); + + ETH_MACConfigTypeDef MACConf; + HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + MACConf.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); + HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + + HAL_ETH_Start_IT( &xEthHandle ); + } + + if( xPhyObject.ulLinkStatusMask != 0U ) + { + xResult = pdPASS; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +{ + BaseType_t xResult = pdFAIL; + + if( pxDescriptor != NULL ) + { + if( xPhyObject.ulLinkStatusMask != 0 ) + { + ETH_BufferTypeDef xTxBuffer = { + .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + + xTxConfig.Length = xTxBuffer.len; + xTxConfig.TxBuffer = &xTxBuffer; + xTxConfig.pData = pxDescriptor; + + if( xTxConfig.Length <= ETH_TX_BUF_SIZE - ipBUFFER_PADDING ) + { + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 20U ) ) != pdFALSE ) + { + xReleaseAfterSend = pdFALSE; + if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) + { + xResult = pdPASS; + } + xSemaphoreGive( xTxMutex ); + } + } + } + } + + if( xReleaseAfterSend != pdFALSE ) + { + vNetworkBufferReleaseFromISR( pxDescriptor ); + } + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvNetworkInterfaceInput( void ) +{ + BaseType_t xResult = 0; + NetworkBufferDescriptor_t * pStartDescriptor = NULL; + while ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pStartDescriptor ) == HAL_OK ) + { + xResult++; + if ( pStartDescriptor != NULL ) + { + const IPStackEvent_t xRxEvent = { + .eEventType = eNetworkRxEvent, + .pvData = ( void * ) pStartDescriptor + }; + + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0U ) != pdPASS ) + { + iptraceETHERNET_RX_EVENT_LOST(); + NetworkBufferDescriptor_t * pxDescriptorToClear = pStartDescriptor; + do + { + NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; + vNetworkBufferReleaseFromISR( pxDescriptorToClear ); + pxDescriptorToClear = pxNext; + } while( pxDescriptorToClear != NULL ); + } + } + } + return ( BaseType_t ) ( xResult > 0 ); +} + +/*-----------------------------------------------------------*/ + +static void prvEMACHandlerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + BaseType_t xResult = 0U; + + uint32_t ulISREvents = 0U; + + if ( xTaskNotifyWait( 0U, EMAC_IF_ALL_EVENT, &ulISREvents, pdMS_TO_TICKS( 500UL ) ) == pdTRUE ) + { + if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) + { + iptraceNETWORK_INTERFACE_RECEIVE(); + xResult = prvNetworkInterfaceInput(); + } + + if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) + { + iptraceNETWORK_INTERFACE_TRANSMIT(); + /*if( xSemaphoreTake( xTxMutex, 250U ) != pdFAIL ) + { + HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xSemaphoreGive( xTxMutex ); + }*/ + } + + if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) + { + HAL_ETH_Stop_IT( &xEthHandle ); + // FreeRTOS_NetworkDown() + /*HAL_ETH_ReleaseTxPacket( &xEthHandle );*/ + HAL_ETH_Start_IT( &xEthHandle ); + } + } + + if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) + { + prvEthernetUpdateConfig(); + } + } +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ) +{ + uint32_t pErrorCode = 0; + HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); + if ( pErrorCode != 0 ) + { + return pdFALSE; + } + + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; + + #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) + { + case ipARP_FRAME_TYPE: + return pdTRUE; + + case ipIPv4_FRAME_TYPE: + break; + + default: + return pdFALSE; + } + #endif + + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + + if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) + { + return pdFALSE; + } + + if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) + { + return pdFALSE; + } + + const uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; + + if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) && ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) + { + return pdFALSE; + } + + if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) + { + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )) + { + return pdFALSE; + } + } + #endif + + return pdTRUE; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) +{ + BaseType_t iResult = -1; + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + { + iResult = 0; + } + return iResult; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) +{ + BaseType_t iResult = -1; + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) + { + iResult = 0; + } + return iResult; +} + +/*-----------------------------------------------------------*/ + +static void prvEthernetUpdateConfig( void ) +{ + if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + { + xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + + ETH_MACConfigTypeDef MACConf; + HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + + if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) + { + MACConf.DuplexMode = ETH_FULLDUPLEX_MODE; + } + else + { + MACConf.DuplexMode = ETH_HALFDUPLEX_MODE; + } + + if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) + { + MACConf.Speed = ETH_SPEED_10M; + } + else + { + MACConf.Speed = ETH_SPEED_100M; + } + + HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + { + HAL_ETH_Start_IT( &xEthHandle ); + } + } + else + { + if( HAL_ETH_Stop_IT( &xEthHandle ) == HAL_OK ) + { + HAL_ETH_ReleaseTxPacket( &xEthHandle ); + memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + } + } +} + +/*-----------------------------------------------------------*/ + +void ETH_IRQHandler( void ) +{ + HAL_ETH_IRQHandler( &xEthHandle ); +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostRXDescsUsed = 0U; + + const size_t uxRxUsed = heth->RxDescList.RxDescCnt; + + if( uxMostRXDescsUsed < uxRxUsed ) + { + uxMostRXDescsUsed = uxRxUsed; + } + + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostTXDescsUsed = 0U; + + const size_t uxTxUsed = heth->TxDescList.BuffersInUse; + + if( uxMostTXDescsUsed < uxTxUsed ) + { + uxMostTXDescsUsed = uxTxUsed; + } + + HAL_ETH_ReleaseTxPacket( heth ); + + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) +{ + uint32_t pErrorCode = 0; + HAL_ETH_GetRxDataErrorCode( heth, &pErrorCode ); + + if ( heth->ErrorCode & HAL_ETH_ERROR_DMA ) + { + if ( heth->DMAErrorCode & ETH_DMASR_FBES ) + { + if( heth->DMAErrorCode & ETH_DMASR_RPS ) + { + /*ETH_DMASR_RPSS + ETH_DMASR_RPS_Queuing + ETH_DMASR_RPS_Closing + ETH_DMASR_RPS_Suspended + ETH_DMASR_RPS_Waiting + ETH_DMASR_RPS_Fetching + ETH_DMASR_RPS_Stopped*/ + } + else if( heth->DMAErrorCode & ETH_DMASR_TPS ) + { + /*ETH_DMASR_TPSS + ETH_DMASR_TPS_Queuing + ETH_DMASR_TPS_Closing + ETH_DMASR_TPS_Suspended + ETH_DMASR_TPS_Waiting + ETH_DMASR_TPS_Fetching + ETH_DMASR_TPS_Stopped*/ + } + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + } + else + { + if( heth->DMAErrorCode & ETH_DMASR_ETS ) + { + return; /* Ignore this */ + } + else if( heth->DMAErrorCode & ETH_DMASR_RWTS ) + { + + } + else if( heth->DMAErrorCode & ETH_DMASR_RBUS ) + { + + } + else if( heth->DMAErrorCode & ETH_DMASR_AIS ) + { + + } + else if( READ_BIT( heth->Instance->DMASR, ETH_DMASR_TBUS ) ) + { + + } + } + + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_MAC ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_PARAM ) + { + return; + } + else if ( heth->ErrorCode == HAL_ETH_ERROR_NONE ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_PARAM ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_BUSY ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_TIMEOUT ) + { + return; + } + /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_RBU ) == ETH_DMACSR_RBU ) + { + xSemaphoreGiveFromISR( xTxMutex ); + } + + if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) + { + xSemaphoreGiveFromISR( xTxMutex ); + }*/ +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxAllocateCallback( uint8_t **buff ) +{ + NetworkBufferDescriptor_t * pxBufferDescriptor = pxNetworkBufferGetFromISR( ETH_RX_BUF_SIZE ); + if( pxBufferDescriptor != NULL ) + { + *buff = pxBufferDescriptor->pucEthernetBuffer; + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) +{ + NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); + if ( prvAcceptPacket( pxCurDescriptor->pucEthernetBuffer ) == pdFALSE ) + { + vNetworkBufferReleaseFromISR( pxCurDescriptor ); + return; + } + NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; + NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; + + pxCurDescriptor->xDataLength = Length; + pxCurDescriptor->pxNextBuffer = NULL; + if( *pStartDescriptor == NULL ) + { + *pStartDescriptor = pxCurDescriptor; + } + else if( pEndDescriptor != NULL ) + { + ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; + } + *pEndDescriptor = pxCurDescriptor; +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_TxFreeCallback( uint32_t *buff ) +{ + NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; + if( pxNetworkBuffer != NULL ) + { + vNetworkBufferReleaseFromISR( pxNetworkBuffer ); + } + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR( xTxDescSem, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_MspInit( ETH_HandleTypeDef* ethHandle ) +{ + if( ethHandle->Instance == ETH ) + { + HAL_ETH_SetMDIOClockRange( ethHandle ); + + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_ETHMAC ); + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_ETHMACTX ); + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_ETHMACRX ); + + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_GPIOA ); + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_GPIOB ); + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_GPIOC ); + LL_AHB1_GRP1_EnableClock( LL_AHB1_GRP1_PERIPH_GPIOG ); + + LL_GPIO_InitTypeDef GPIO_InitStruct = { + .Mode = LL_GPIO_MODE_ALTERNATE, + .Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH, + .OutputType = LL_GPIO_OUTPUT_PUSHPULL, + .Pull = LL_GPIO_PULL_NO, + .Alternate = LL_GPIO_AF_11 + }; + + GPIO_InitStruct.Pin = ETH_MDC_Pin | ETH_RXD0_Pin | ETH_RXD1_Pin; + LL_GPIO_Init( GPIOC, &GPIO_InitStruct ); + + GPIO_InitStruct.Pin = ETH_REF_CLK_Pin | ETH_MDIO_Pin | ETH_CRS_DV_Pin; + LL_GPIO_Init( GPIOA, &GPIO_InitStruct ); + + GPIO_InitStruct.Pin = ETH_TXD1_Pin; + LL_GPIO_Init( GPIOB, &GPIO_InitStruct ); + + GPIO_InitStruct.Pin = ETH_TX_EN_Pin | ETH_TXD0_Pin; + LL_GPIO_Init( GPIOG, &GPIO_InitStruct ); + + NVIC_SetPriority( ETH_IRQn, NVIC_EncodePriority( NVIC_GetPriorityGrouping(), 5, 0 ) ); + NVIC_EnableIRQ( ETH_IRQn ); + } +} + +/*-----------------------------------------------------------*/ diff --git a/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld b/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld new file mode 100644 index 0000000000..838406daf1 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld @@ -0,0 +1,205 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** Abstract : Linker script for NUCLEO-F767ZI Board embedding STM32F767ZITx Device from stm32f7 series +** 2048Kbytes FLASH +** 512Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2022 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 8K; /* required amount of heap */ +_Min_Stack_Size = 4K; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 447K + RAM_NO_CACHE (rwx) : ORIGIN = 0x2006FC00, LENGTH = 65K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + .EthDescriptorsBlock (NOLOAD) : + { + . = ALIGN(1K); + __ETH_DESCRIPTORS_START = .; + *(.RxDescripSection) + *(.TxDescripSection) + . = ALIGN(1K); + __ETH_DESCRIPTORS_END = .; + } >RAM_NO_CACHE + + .EthBuffersBlock (NOLOAD) : + { + . = ALIGN(64K); + __ETH_BUFFERS_START = .; + *(.EthBuffersSection) + . = ALIGN(64K); + __ETH_BUFFERS_END = .; + } >RAM_NO_CACHE + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/source/portable/NetworkInterface/STM32/mpu.c b/source/portable/NetworkInterface/STM32/mpu.c new file mode 100644 index 0000000000..d84f05dd41 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/mpu.c @@ -0,0 +1,31 @@ +#include "main.h" +#include "mpu.h" + +void MPU_Config(void) +{ + LL_MPU_Disable(); + + extern int __ETH_DESCRIPTORS_START, __ETH_BUFFERS_START; + + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER0, + 0x0, + ( uint32_t )&__ETH_DESCRIPTORS_START, + LL_MPU_REGION_SIZE_1KB|LL_MPU_TEX_LEVEL0|LL_MPU_REGION_FULL_ACCESS|\ + LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ + LL_MPU_ACCESS_BUFFERABLE + ); + LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0); + + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER1, + 0x0, + ( uint32_t )&__ETH_BUFFERS_START, + LL_MPU_REGION_SIZE_64KB|LL_MPU_TEX_LEVEL1|LL_MPU_REGION_FULL_ACCESS|\ + LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ + LL_MPU_ACCESS_NOT_BUFFERABLE + ); + LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER1); + + LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); +} From 3b9295305a8d2d5324a5d997208abc72d3b45b90 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 20 Mar 2023 23:04:28 -0400 Subject: [PATCH 02/68] New STM32 driver --- .../Legacy}/STM32Fxx/CMakeLists.txt | 0 .../Legacy}/STM32Fxx/NetworkInterface.c | 0 .../{ => STM32/Legacy}/STM32Fxx/readme.md | 0 .../Legacy}/STM32Fxx/stm32f2xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32f4xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32f7xx_hal_eth.h | 0 .../Legacy}/STM32Fxx/stm32fxx_hal_eth.c | 0 .../Legacy}/STM32Fxx/stm32fxx_hal_eth.h | 0 .../Legacy}/STM32Hxx/CMakeLists.txt | 0 .../Legacy}/STM32Hxx/NetworkInterface.c | 0 .../{ => STM32/Legacy}/STM32Hxx/readme.md | 0 .../Legacy}/STM32Hxx/stm32h7xx_hal_eth.h | 0 .../Legacy}/STM32Hxx/stm32hxx_hal_eth.c | 0 .../Legacy}/STM32Hxx/stm32hxx_hal_eth.h | 0 .../NetworkInterface/STM32/NetworkInterface.c | 644 ++++++++++++++++++ .../STM32/STM32F767ZITX_FLASH.ld | 205 ++++++ source/portable/NetworkInterface/STM32/mpu.c | 31 + 17 files changed, 880 insertions(+) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/CMakeLists.txt (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/NetworkInterface.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/readme.md (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f2xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f4xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32f7xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32fxx_hal_eth.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Fxx/stm32fxx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/CMakeLists.txt (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/NetworkInterface.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/readme.md (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32h7xx_hal_eth.h (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32hxx_hal_eth.c (100%) rename source/portable/NetworkInterface/{ => STM32/Legacy}/STM32Hxx/stm32hxx_hal_eth.h (100%) create mode 100644 source/portable/NetworkInterface/STM32/NetworkInterface.c create mode 100644 source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld create mode 100644 source/portable/NetworkInterface/STM32/mpu.c diff --git a/source/portable/NetworkInterface/STM32Fxx/CMakeLists.txt b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/CMakeLists.txt similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/CMakeLists.txt rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/CMakeLists.txt diff --git a/source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/NetworkInterface.c similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/NetworkInterface.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/NetworkInterface.c diff --git a/source/portable/NetworkInterface/STM32Fxx/readme.md b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/readme.md similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/readme.md rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/readme.md diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f2xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f2xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f2xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f2xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f4xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f4xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f4xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f4xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32f7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f7xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32f7xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32f7xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.c similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.c diff --git a/source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Fxx/stm32fxx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Fxx/stm32fxx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Hxx/CMakeLists.txt b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/CMakeLists.txt similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/CMakeLists.txt rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/CMakeLists.txt diff --git a/source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/NetworkInterface.c similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/NetworkInterface.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/NetworkInterface.c diff --git a/source/portable/NetworkInterface/STM32Hxx/readme.md b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/readme.md similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/readme.md rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/readme.md diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32h7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32h7xx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32h7xx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32h7xx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.c b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.c similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.c rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.c diff --git a/source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.h b/source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.h similarity index 100% rename from source/portable/NetworkInterface/STM32Hxx/stm32hxx_hal_eth.h rename to source/portable/NetworkInterface/STM32/Legacy/STM32Hxx/stm32hxx_hal_eth.h diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c new file mode 100644 index 0000000000..28590d7436 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -0,0 +1,644 @@ +/* + * Some constants, hardware definitions and comments taken from ST's HAL driver + * library, COPYRIGHT(c) 2015 STMicroelectronics. + */ + +/* + * FreeRTOS+TCP + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * 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 +#include +#include + +/* 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 "NetworkBufferManagement.h" +#include "NetworkInterface.h" +#include "phyHandling.h" + +/* ST includes. */ +#include "main.h" +#include "stm32f7xx_hal_eth.h" + +/*-----------------------------------------------------------*/ + +#define NETWORK_BUFFER_SIZE ( ( ( ETH_RX_BUF_SIZE + ipBUFFER_PADDING ) + 7 ) & ~0x7UL ) + +#define EMAC_IF_RX_EVENT 1UL +#define EMAC_IF_TX_EVENT 2UL +#define EMAC_IF_ERR_EVENT 4UL +#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT ) + +/*-----------------------------------------------------------*/ + +static BaseType_t prvNetworkInterfaceInput( void ); + +static void prvEMACHandlerTask( void * pvParameters ) __attribute__((__noreturn__)); + +static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ); + +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); + +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); + +static void prvEthernetUpdateConfig( void ); + +/*-----------------------------------------------------------*/ + +static ETH_HandleTypeDef xEthHandle; + +static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ) ) ); + +static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ) ) ); + +static ETH_TxPacketConfig xTxConfig; + +static TaskHandle_t xEMACTaskHandle; + +static SemaphoreHandle_t xTxMutex; + +static SemaphoreHandle_t xTxDescSem; + +static EthernetPhy_t xPhyObject; + +static const PhyProperties_t xPHYProperties = { + .ucSpeed = PHY_SPEED_AUTO, + .ucDuplex = PHY_DUPLEX_AUTO, + .ucMDI_X = PHY_MDIX_AUTO, +}; + +/*-----------------------------------------------------------*/ + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ NETWORK_BUFFER_SIZE ] __attribute__( ( aligned( 4 ), section( ".EthBuffersSection" ) ) ); + + for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + { + pxNetworkBuffers[ ul ].pucEthernetBuffer = &( ucNetworkPackets[ ul ][ ipBUFFER_PADDING ] ); + *( ( uint32_t * ) &( ucNetworkPackets[ ul ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ ul ] ) ); + } +} + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + BaseType_t xResult = pdFAIL; + + if( xEMACTaskHandle == NULL ) + { + static StaticSemaphore_t xTxMutexBuf; + xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + configASSERT( xTxMutex ); + vQueueAddToRegistry( xTxMutex, "TXMutex" ); + + static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); + configASSERT( xTxDescSem ); + vQueueAddToRegistry( xTxDescSem, "xTxDescSem" ); + + static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; + static StaticTask_t xEMACTaskTCB; + xEMACTaskHandle = xTaskCreateStatic( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + uxEMACTaskStack, + &xEMACTaskTCB + ); + configASSERT( xEMACTaskHandle ); + } + + if( xEthHandle.Instance == NULL ) + { + xEthHandle.Instance = ETH; + xEthHandle.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; + xEthHandle.Init.TxDesc = DMATxDscrTab; + xEthHandle.Init.RxDesc = DMARxDscrTab; + xEthHandle.Init.RxBuffLen = ETH_RX_BUF_SIZE; + + memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); + + HAL_ETH_SetMDIOClockRange( &xEthHandle ); + + configASSERT( HAL_ETH_Init( &xEthHandle ) == HAL_OK ); + + memset( &xTxConfig, 0, sizeof( xTxConfig ) ); + xTxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM; + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + xTxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; + + vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); + configASSERT( xPhyDiscover( &xPhyObject ) > 0 ); + configASSERT( xPhyConfigure( &xPhyObject, &xPHYProperties ) == 0 ); + configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); + + ETH_MACConfigTypeDef MACConf; + HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + MACConf.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); + HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + + HAL_ETH_Start_IT( &xEthHandle ); + } + + if( xPhyObject.ulLinkStatusMask != 0U ) + { + xResult = pdPASS; + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +{ + BaseType_t xResult = pdFAIL; + + if( pxDescriptor != NULL ) + { + if( xPhyObject.ulLinkStatusMask != 0 ) + { + ETH_BufferTypeDef xTxBuffer = { + .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + + xTxConfig.Length = xTxBuffer.len; + xTxConfig.TxBuffer = &xTxBuffer; + xTxConfig.pData = pxDescriptor; + + if( xTxConfig.Length <= ETH_TX_BUF_SIZE - ipBUFFER_PADDING ) + { + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 20U ) ) != pdFALSE ) + { + xReleaseAfterSend = pdFALSE; + if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) + { + xResult = pdPASS; + } + xSemaphoreGive( xTxMutex ); + } + } + } + } + + if( xReleaseAfterSend != pdFALSE ) + { + vNetworkBufferReleaseFromISR( pxDescriptor ); + } + } + + return xResult; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvNetworkInterfaceInput( void ) +{ + BaseType_t xResult = 0; + NetworkBufferDescriptor_t * pStartDescriptor = NULL; + while ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pStartDescriptor ) == HAL_OK ) + { + xResult++; + if ( pStartDescriptor != NULL ) + { + const IPStackEvent_t xRxEvent = { + .eEventType = eNetworkRxEvent, + .pvData = ( void * ) pStartDescriptor + }; + + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0U ) != pdPASS ) + { + iptraceETHERNET_RX_EVENT_LOST(); + NetworkBufferDescriptor_t * pxDescriptorToClear = pStartDescriptor; + do + { + NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; + vNetworkBufferReleaseFromISR( pxDescriptorToClear ); + pxDescriptorToClear = pxNext; + } while( pxDescriptorToClear != NULL ); + } + } + } + return ( BaseType_t ) ( xResult > 0 ); +} + +/*-----------------------------------------------------------*/ + +static void prvEMACHandlerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + for( ;; ) + { + BaseType_t xResult = 0U; + + uint32_t ulISREvents = 0U; + + if ( xTaskNotifyWait( 0U, EMAC_IF_ALL_EVENT, &ulISREvents, pdMS_TO_TICKS( 500UL ) ) == pdTRUE ) + { + if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) + { + iptraceNETWORK_INTERFACE_RECEIVE(); + xResult = prvNetworkInterfaceInput(); + } + + if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) + { + iptraceNETWORK_INTERFACE_TRANSMIT(); + /*if( xSemaphoreTake( xTxMutex, 250U ) != pdFAIL ) + { + HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xSemaphoreGive( xTxMutex ); + }*/ + } + + if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) + { + HAL_ETH_Stop_IT( &xEthHandle ); + // FreeRTOS_NetworkDown() + /*HAL_ETH_ReleaseTxPacket( &xEthHandle );*/ + HAL_ETH_Start_IT( &xEthHandle ); + } + } + + if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) + { + prvEthernetUpdateConfig(); + } + } +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ) +{ + uint32_t pErrorCode = 0; + HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); + if ( pErrorCode != 0 ) + { + return pdFALSE; + } + + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; + + #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) + { + case ipARP_FRAME_TYPE: + return pdTRUE; + + case ipIPv4_FRAME_TYPE: + break; + + default: + return pdFALSE; + } + #endif + + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + + if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) + { + return pdFALSE; + } + + if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) + { + return pdFALSE; + } + + const uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; + + if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) && ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) + { + return pdFALSE; + } + + if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) + { + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )) + { + return pdFALSE; + } + } + #endif + + return pdTRUE; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) +{ + BaseType_t iResult = -1; + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + { + iResult = 0; + } + return iResult; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) +{ + BaseType_t iResult = -1; + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) + { + iResult = 0; + } + return iResult; +} + +/*-----------------------------------------------------------*/ + +static void prvEthernetUpdateConfig( void ) +{ + if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + { + xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + + ETH_MACConfigTypeDef MACConf; + HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + + if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) + { + MACConf.DuplexMode = ETH_FULLDUPLEX_MODE; + } + else + { + MACConf.DuplexMode = ETH_HALFDUPLEX_MODE; + } + + if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) + { + MACConf.Speed = ETH_SPEED_10M; + } + else + { + MACConf.Speed = ETH_SPEED_100M; + } + + HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + { + HAL_ETH_Start_IT( &xEthHandle ); + } + } + else + { + if( HAL_ETH_Stop_IT( &xEthHandle ) == HAL_OK ) + { + HAL_ETH_ReleaseTxPacket( &xEthHandle ); + memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + } + } +} + +/*-----------------------------------------------------------*/ + +void ETH_IRQHandler( void ) +{ + HAL_ETH_IRQHandler( &xEthHandle ); +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostRXDescsUsed = 0U; + + const size_t uxRxUsed = heth->RxDescList.RxDescCnt; + + if( uxMostRXDescsUsed < uxRxUsed ) + { + uxMostRXDescsUsed = uxRxUsed; + } + + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostTXDescsUsed = 0U; + + const size_t uxTxUsed = heth->TxDescList.BuffersInUse; + + if( uxMostTXDescsUsed < uxTxUsed ) + { + uxMostTXDescsUsed = uxTxUsed; + } + + HAL_ETH_ReleaseTxPacket( heth ); + + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) +{ + uint32_t pErrorCode = 0; + HAL_ETH_GetRxDataErrorCode( heth, &pErrorCode ); + + if ( heth->ErrorCode & HAL_ETH_ERROR_DMA ) + { + if ( heth->DMAErrorCode & ETH_DMASR_FBES ) + { + if( heth->DMAErrorCode & ETH_DMASR_RPS ) + { + /*ETH_DMASR_RPSS + ETH_DMASR_RPS_Queuing + ETH_DMASR_RPS_Closing + ETH_DMASR_RPS_Suspended + ETH_DMASR_RPS_Waiting + ETH_DMASR_RPS_Fetching + ETH_DMASR_RPS_Stopped*/ + } + else if( heth->DMAErrorCode & ETH_DMASR_TPS ) + { + /*ETH_DMASR_TPSS + ETH_DMASR_TPS_Queuing + ETH_DMASR_TPS_Closing + ETH_DMASR_TPS_Suspended + ETH_DMASR_TPS_Waiting + ETH_DMASR_TPS_Fetching + ETH_DMASR_TPS_Stopped*/ + } + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + } + else + { + if( heth->DMAErrorCode & ETH_DMASR_ETS ) + { + return; /* Ignore this */ + } + else if( heth->DMAErrorCode & ETH_DMASR_RWTS ) + { + + } + else if( heth->DMAErrorCode & ETH_DMASR_RBUS ) + { + + } + else if( heth->DMAErrorCode & ETH_DMASR_AIS ) + { + + } + else if( READ_BIT( heth->Instance->DMASR, ETH_DMASR_TBUS ) ) + { + + } + } + + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_MAC ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_PARAM ) + { + return; + } + else if ( heth->ErrorCode == HAL_ETH_ERROR_NONE ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_PARAM ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_BUSY ) + { + return; + } + else if ( heth->ErrorCode & HAL_ETH_ERROR_TIMEOUT ) + { + return; + } + /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_RBU ) == ETH_DMACSR_RBU ) + { + xSemaphoreGiveFromISR( xTxMutex ); + } + + if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) + { + xSemaphoreGiveFromISR( xTxMutex ); + }*/ +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxAllocateCallback( uint8_t **buff ) +{ + NetworkBufferDescriptor_t * pxBufferDescriptor = pxNetworkBufferGetFromISR( ETH_RX_BUF_SIZE ); + if( pxBufferDescriptor != NULL ) + { + *buff = pxBufferDescriptor->pucEthernetBuffer; + } +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) +{ + NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); + if ( prvAcceptPacket( pxCurDescriptor->pucEthernetBuffer ) == pdFALSE ) + { + vNetworkBufferReleaseFromISR( pxCurDescriptor ); + return; + } + NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; + NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; + + pxCurDescriptor->xDataLength = Length; + pxCurDescriptor->pxNextBuffer = NULL; + if( *pStartDescriptor == NULL ) + { + *pStartDescriptor = pxCurDescriptor; + } + else if( pEndDescriptor != NULL ) + { + ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; + } + *pEndDescriptor = pxCurDescriptor; +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_TxFreeCallback( uint32_t *buff ) +{ + NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; + if( pxNetworkBuffer != NULL ) + { + vNetworkBufferReleaseFromISR( pxNetworkBuffer ); + } + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xSemaphoreGiveFromISR( xTxDescSem, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +/*-----------------------------------------------------------*/ diff --git a/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld b/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld new file mode 100644 index 0000000000..838406daf1 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/STM32F767ZITX_FLASH.ld @@ -0,0 +1,205 @@ +/* +****************************************************************************** +** +** @file : LinkerScript.ld +** +** @author : Auto-generated by STM32CubeIDE +** +** Abstract : Linker script for NUCLEO-F767ZI Board embedding STM32F767ZITx Device from stm32f7 series +** 2048Kbytes FLASH +** 512Kbytes RAM +** +** Set heap size, stack size and stack location according +** to application requirements. +** +** Set memory bank area and size if external memory is used +** +** Target : STMicroelectronics STM32 +** +** Distribution: The file is distributed as is, without any warranty +** of any kind. +** +****************************************************************************** +** @attention +** +** Copyright (c) 2022 STMicroelectronics. +** All rights reserved. +** +** This software is licensed under terms that can be found in the LICENSE file +** in the root directory of this software component. +** If no LICENSE file comes with this software, it is provided AS-IS. +** +****************************************************************************** +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +/* Highest address of the user mode stack */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ + +_Min_Heap_Size = 8K; /* required amount of heap */ +_Min_Stack_Size = 4K; /* required amount of stack */ + +/* Memories definition */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 447K + RAM_NO_CACHE (rwx) : ORIGIN = 0x2006FC00, LENGTH = 65K +} + +/* Sections */ +SECTIONS +{ + /* The startup code into "FLASH" Rom type memory */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data into "FLASH" Rom type memory */ + .text : + { + . = ALIGN(4); + *(.text) /* .text sections (code) */ + *(.text*) /* .text* sections (code) */ + *(.glue_7) /* glue arm to thumb code */ + *(.glue_7t) /* glue thumb to arm code */ + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; /* define a global symbols at end of code */ + } >FLASH + + /* Constant data into "FLASH" Rom type memory */ + .rodata : + { + . = ALIGN(4); + *(.rodata) /* .rodata sections (constants, strings, etc.) */ + *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ + . = ALIGN(4); + } >FLASH + + .ARM.extab : { + . = ALIGN(4); + *(.ARM.extab* .gnu.linkonce.armextab.*) + . = ALIGN(4); + } >FLASH + + .ARM : { + . = ALIGN(4); + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + . = ALIGN(4); + } >FLASH + + .preinit_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + . = ALIGN(4); + } >FLASH + + .init_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + . = ALIGN(4); + } >FLASH + + .fini_array : + { + . = ALIGN(4); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + . = ALIGN(4); + } >FLASH + + /* Used by the startup to initialize data */ + _sidata = LOADADDR(.data); + + /* Initialized data sections into "RAM" Ram type memory */ + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + *(.RamFunc) /* .RamFunc sections */ + *(.RamFunc*) /* .RamFunc* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + + } >RAM AT> FLASH + + /* Uninitialized data section into "RAM" Ram type memory */ + . = ALIGN(4); + .bss : + { + /* This is used by the startup in order to initialize the .bss section */ + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } >RAM + + /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM + + .EthDescriptorsBlock (NOLOAD) : + { + . = ALIGN(1K); + __ETH_DESCRIPTORS_START = .; + *(.RxDescripSection) + *(.TxDescripSection) + . = ALIGN(1K); + __ETH_DESCRIPTORS_END = .; + } >RAM_NO_CACHE + + .EthBuffersBlock (NOLOAD) : + { + . = ALIGN(64K); + __ETH_BUFFERS_START = .; + *(.EthBuffersSection) + . = ALIGN(64K); + __ETH_BUFFERS_END = .; + } >RAM_NO_CACHE + + /* Remove information from the compiler libraries */ + /DISCARD/ : + { + libc.a ( * ) + libm.a ( * ) + libgcc.a ( * ) + } + + .ARM.attributes 0 : { *(.ARM.attributes) } +} diff --git a/source/portable/NetworkInterface/STM32/mpu.c b/source/portable/NetworkInterface/STM32/mpu.c new file mode 100644 index 0000000000..d84f05dd41 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/mpu.c @@ -0,0 +1,31 @@ +#include "main.h" +#include "mpu.h" + +void MPU_Config(void) +{ + LL_MPU_Disable(); + + extern int __ETH_DESCRIPTORS_START, __ETH_BUFFERS_START; + + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER0, + 0x0, + ( uint32_t )&__ETH_DESCRIPTORS_START, + LL_MPU_REGION_SIZE_1KB|LL_MPU_TEX_LEVEL0|LL_MPU_REGION_FULL_ACCESS|\ + LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ + LL_MPU_ACCESS_BUFFERABLE + ); + LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0); + + LL_MPU_ConfigRegion( + LL_MPU_REGION_NUMBER1, + 0x0, + ( uint32_t )&__ETH_BUFFERS_START, + LL_MPU_REGION_SIZE_64KB|LL_MPU_TEX_LEVEL1|LL_MPU_REGION_FULL_ACCESS|\ + LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ + LL_MPU_ACCESS_NOT_BUFFERABLE + ); + LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER1); + + LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); +} From bffd9afeab0522f070b38aa7792a9c36af77c2df Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 24 Mar 2023 13:06:20 -0400 Subject: [PATCH 03/68] Fix isr usage, add F4, and add missing xGetPhyLinkStatus --- .../NetworkInterface/STM32/NetworkInterface.c | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 3cdf6450ee..ff22d3210e 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -49,8 +49,9 @@ #include "phyHandling.h" /* ST includes. */ -#include "main.h" -#if defined(STM32F7) +#if defined(STM32F4) + #include "stm32f4xx_hal_eth.h" +#elif defined(STM32F7) #include "stm32f7xx_hal_eth.h" #elif defined(STM32H7) #include "stm32h7xx_hal_eth.h" @@ -167,6 +168,23 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB /*-----------------------------------------------------------*/ +BaseType_t xGetPhyLinkStatus( void ) +{ + BaseType_t xReturn; + + if( xPhyObject.ulLinkStatusMask != 0U ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + BaseType_t xNetworkInterfaceInitialise( void ) { BaseType_t xResult = pdFAIL; @@ -218,7 +236,7 @@ BaseType_t xNetworkInterfaceInitialise( void ) memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); - #ifdef STM32F7 + #if defined(STM32F7) || defined(STM32F4) /* This function doesn't get called in Fxx driver */ HAL_ETH_SetMDIOClockRange( &xEthHandle ); #endif @@ -262,7 +280,7 @@ BaseType_t xNetworkInterfaceInitialise( void ) configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); } - if ( xPhyObject.ulLinkStatusMask != 0U ) + if ( xGetPhyLinkStatus() != pdFAIL ) { ETH_MACConfigTypeDef MACConf; configASSERT( HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ) == HAL_OK ); @@ -286,7 +304,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript if( pxDescriptor != NULL ) { - if( xPhyObject.ulLinkStatusMask != 0 ) + if( xGetPhyLinkStatus() != pdFAIL ) { ETH_BufferTypeDef xTxBuffer = { .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, @@ -513,7 +531,7 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static void prvEthernetUpdateConfig( void ) { - if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + if( xGetPhyLinkStatus() != pdFAIL ) { /* TODO: if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE ) */ configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); @@ -540,7 +558,7 @@ static void prvEthernetUpdateConfig( void ) } configASSERT( HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ) == HAL_OK ); - if( ( xPhyObject.ulLinkStatusMask != 0 ) ) + if( xGetPhyLinkStatus() != pdFAIL ) { HAL_ETH_Start_IT( &xEthHandle ); } @@ -549,6 +567,7 @@ static void prvEthernetUpdateConfig( void ) { if( HAL_ETH_Stop_IT( &xEthHandle ) == HAL_OK ) { + /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ configASSERT( HAL_ETH_ReleaseTxPacket( &xEthHandle ) == HAL_OK ); memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); } @@ -596,8 +615,6 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) uxMostTXDescsUsed = uxTxUsed; } - /* configASSERT( HAL_ETH_ReleaseTxPacket( heth ) == HAL_OK ); */ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); @@ -624,14 +641,16 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { /* F7 - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ /* H7 - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ + /* TODO: Check if allocated in HAL_ETH_RxAllocateCallback before error interrupt, then release here */ /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_RBU ) == ETH_DMACSR_RBU ) { - xSemaphoreGiveFromISR( xTxMutex ); - } - if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) + }*/ + /* TODO: same as above but for Tx */ + /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) { xSemaphoreGiveFromISR( xTxMutex ); + xSemaphoreGiveFromISR( xTxDescSem ); }*/ } } @@ -652,7 +671,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) void HAL_ETH_RxAllocateCallback( uint8_t **buff ) { - NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, pdMS_TO_TICKS( 0 ) ); + NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, pdMS_TO_TICKS( 20U ) ); if( pxBufferDescriptor != NULL ) { *buff = pxBufferDescriptor->pucEthernetBuffer; @@ -700,9 +719,7 @@ void HAL_ETH_TxFreeCallback( uint32_t *buff ) { vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); } - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR( xTxDescSem, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + xSemaphoreGive( xTxDescSem ); } /*-----------------------------------------------------------*/ From 2beff06aa55cf86e41b40ac8e08e108196363e4a Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 25 Mar 2023 13:26:32 -0400 Subject: [PATCH 04/68] Style fixes and config implementations --- .../NetworkInterface/STM32/NetworkInterface.c | 506 +++++++++++------- 1 file changed, 299 insertions(+), 207 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index ff22d3210e..1cf79a7276 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -55,12 +55,47 @@ #include "stm32f7xx_hal_eth.h" #elif defined(STM32H7) #include "stm32h7xx_hal_eth.h" +#elif defined(STM32H5) + /* Untested */ + #include "stm32h5xx_hal_eth.h" #else #error Unknown STM32 Family for NetworkInterface #endif /*-----------------------------------------------------------*/ +/* TODO: Should these be moved to FreeRTOSIPConfigDefaults.h? */ +#ifndef ipconfigETHERNET_AN_ENABLE + #define ipconfigETHERNET_AN_ENABLE 1 +#endif + +#if ( ipconfigETHERNET_AN_ENABLE == 0 ) + #ifndef ipconfigETHERNET_USE_100MB + #define ipconfigETHERNET_USE_100MB 1 + #endif + + #ifndef ipconfigETHERNET_USE_FULL_DUPLEX + #define ipconfigETHERNET_USE_FULL_DUPLEX 1 + #endif +#endif + +#ifndef ipconfigETHERNET_AUTO_CROSS_ENABLE + #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1 +#endif + +#if ( ipconfigETHERNET_AUTO_CROSS_ENABLE == 0 ) + #ifndef ipconfigETHERNET_CROSSED_LINK + #define ipconfigETHERNET_CROSSED_LINK 0 + #endif +#endif + +#ifndef ipconfigUSE_RMII + #define ipconfigUSE_RMII 1 +#endif + +/*-----------------------------------------------------------*/ + +/* TODO: Verify this size */ #define NETWORK_BUFFER_SIZE ( ( ( ETH_RX_BUF_SIZE + ipBUFFER_PADDING ) + 7 ) & ~0x7UL ) #define EMAC_IF_RX_EVENT 1UL @@ -70,9 +105,9 @@ typedef enum { - eMACInit, /* Must initialise MAC. */ - eMACPass, /* Initialisation was successful. */ - eMACFailed, /* Initialisation failed. */ + eMACInit, + eMACPass, + eMACFailed } eMAC_INIT_STATUS_TYPE; /*-----------------------------------------------------------*/ @@ -95,19 +130,22 @@ static ETH_HandleTypeDef xEthHandle; static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ) ) ); +/* TODO: implement ( ipconfigZERO_COPY_RX_DRIVER == 0 ) */ /*#if ( ipconfigZERO_COPY_RX_DRIVER == 0 ) - __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; + __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RX_DESC_CNT ][ ETH_RX_BUF_SIZE ] __ALIGN_END; #endif*/ static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ) ) ); +/* TODO: implement ( ipconfigZERO_COPY_TX_DRIVER == 0 ) */ /*#if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) - __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; + __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TX_DESC_CNT ][ ETH_TX_BUF_SIZE ] __ALIGN_END; #endif*/ static ETH_TxPacketConfig xTxConfig; -/*#if ( ipconfigUSE_LLMNR == 1 ) +/* TODO: implement ( ipconfigUSE_LLMNR != 0 ) */ +/*#if ( ipconfigUSE_LLMNR != 0 ) static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; #endif*/ @@ -115,17 +153,13 @@ static TaskHandle_t xEMACTaskHandle; static SemaphoreHandle_t xTxMutex; -static SemaphoreHandle_t xTxDescSem; +/* TODO: uncomment this after chaining Tx Buffers */ +/* xTxDescSem is not useful unless xTxBuffer.next != NULL */ +/* static SemaphoreHandle_t xTxDescSem; */ static EthernetPhy_t xPhyObject; -static const PhyProperties_t xPHYProperties = { - .ucSpeed = PHY_SPEED_AUTO, - .ucDuplex = PHY_DUPLEX_AUTO, - .ucMDI_X = PHY_MDIX_AUTO, -}; - -/* static const PhyProperties_t xPHYProperties = +static const PhyProperties_t xPHYProperties = { #if ( ipconfigETHERNET_AN_ENABLE != 0 ) .ucSpeed = PHY_SPEED_AUTO, @@ -151,7 +185,7 @@ static const PhyProperties_t xPHYProperties = { #else .ucMDI_X = PHY_MDIX_DIRECT, #endif -}; */ +}; /*-----------------------------------------------------------*/ @@ -170,16 +204,12 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB BaseType_t xGetPhyLinkStatus( void ) { - BaseType_t xReturn; + BaseType_t xReturn = pdFAIL; if( xPhyObject.ulLinkStatusMask != 0U ) { xReturn = pdPASS; } - else - { - xReturn = pdFAIL; - } return xReturn; } @@ -188,6 +218,8 @@ BaseType_t xGetPhyLinkStatus( void ) BaseType_t xNetworkInterfaceInitialise( void ) { BaseType_t xResult = pdFAIL; + BaseType_t xPhyResult; + HAL_StatusTypeDef xHalResult; static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; @@ -195,27 +227,52 @@ BaseType_t xNetworkInterfaceInitialise( void ) { if( xEMACTaskHandle == NULL ) { - static StaticSemaphore_t xTxMutexBuf; - xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + static StaticSemaphore_t xTxMutexBuf; + xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + + /* TODO: uncomment this after chaining Tx Buffers */ + /* static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); */ + + static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; + static StaticTask_t xEMACTaskTCB; + /* TODO: Allow stack size & priority to be defined */ + xEMACTaskHandle = xTaskCreateStatic( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + uxEMACTaskStack, + &xEMACTaskTCB + ); + #else + xTxMutex = xSemaphoreCreateMutex(); + + /* TODO: uncomment this after chaining Tx Buffers */ + /*xTxDescSem = xSemaphoreCreateCounting( + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + );*/ + + /* TODO: Allow stack size & priority to be defined */ + ( void ) xTaskCreate( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + &xEMACTaskHandle + ); + #endif configASSERT( xTxMutex ); vQueueAddToRegistry( xTxMutex, "TXMutex" ); - static StaticSemaphore_t xTxDescSemBuf; - xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); - configASSERT( xTxDescSem ); - vQueueAddToRegistry( xTxDescSem, "xTxDescSem" ); - - static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; - static StaticTask_t xEMACTaskTCB; - xEMACTaskHandle = xTaskCreateStatic( - prvEMACHandlerTask, - "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), - NULL, - ( configMAX_PRIORITIES - 1 ), - uxEMACTaskStack, - &xEMACTaskTCB - ); + /* TODO: uncomment this after chaining Tx Buffers */ + /*configASSERT( xTxDescSem ); + vQueueAddToRegistry( xTxDescSem, "xTxDescSem" );*/ + configASSERT( xEMACTaskHandle ); } @@ -223,14 +280,10 @@ BaseType_t xNetworkInterfaceInitialise( void ) { xEthHandle.Instance = ETH; xEthHandle.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); - xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; - /*#if ( ipconfigUSE_RMII != 0 ) - xEthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; - #else - xEthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; - #endif*/ + xEthHandle.Init.MediaInterface = ( ipconfigUSE_RMII != 0 ) ? HAL_ETH_RMII_MODE : HAL_ETH_MII_MODE; xEthHandle.Init.TxDesc = DMATxDscrTab; xEthHandle.Init.RxDesc = DMARxDscrTab; + /* TODO: Verify RxBuffLen size */ xEthHandle.Init.RxBuffLen = ETH_RX_BUF_SIZE; memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); @@ -241,21 +294,28 @@ BaseType_t xNetworkInterfaceInitialise( void ) HAL_ETH_SetMDIOClockRange( &xEthHandle ); #endif - configASSERT( HAL_ETH_Init( &xEthHandle ) == HAL_OK ); + xHalResult = HAL_ETH_Init( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); + /* TODO: uncomment & test these */ /*#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) BaseType_t xMACEntry = ETH_MAC_ADDRESS1; uint8_t pMACAddr[6]; memset( &pMACAddr, 0, sizeof( pMACAddr ) ); - configASSERT( HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, pMACAddr ) ); + xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, pMACAddr ); + configASSERT( xHalResult == HAL_OK ); #endif - #if ( ipconfigUSE_MDNS == 1 ) - HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xMDNS_MACAddressIPv4 ); + #if ( ipconfigUSE_MDNS != 0 ) + xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xMDNS_MACAddressIPv4 ); + configASSERT( xHalResult == HAL_OK ); xMACEntry += 8; #endif - #if ( ipconfigUSE_LLMNR == 1 ) - HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xLLMNR_MACAddress ); + #if ( ipconfigUSE_LLMNR != 0 ) + xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xLLMNR_MACAddress ); + configASSERT( xHalResult == HAL_OK ); xMACEntry += 8; #endif*/ @@ -275,20 +335,26 @@ BaseType_t xNetworkInterfaceInitialise( void ) if( xMacInitStatus == eMACPass ) { vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); - configASSERT( xPhyDiscover( &xPhyObject ) > 0 ); - configASSERT( xPhyConfigure( &xPhyObject, &xPHYProperties ) == 0 ); - configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); + xPhyResult = xPhyDiscover( &xPhyObject ); + configASSERT( xPhyResult > 0 ); + xPhyResult = xPhyConfigure( &xPhyObject, &xPHYProperties ); + configASSERT( xPhyResult == 0 ); + xPhyResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + configASSERT( xPhyResult == 0 ); } if ( xGetPhyLinkStatus() != pdFAIL ) { ETH_MACConfigTypeDef MACConf; - configASSERT( HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ) == HAL_OK ); + xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + configASSERT( xHalResult == HAL_OK ); MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; MACConf.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); - configASSERT( HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ) == HAL_OK ); - configASSERT( HAL_ETH_Start_IT( &xEthHandle ) == HAL_OK ); + xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + configASSERT( xHalResult == HAL_OK ); + xHalResult = HAL_ETH_Start_IT( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); xResult = pdPASS; } @@ -306,6 +372,7 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript { if( xGetPhyLinkStatus() != pdFAIL ) { + /* TODO: Tx Optimization by setting .next? */ ETH_BufferTypeDef xTxBuffer = { .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, .len = pxDescriptor->xDataLength, @@ -318,30 +385,36 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript if( xTxConfig.Length <= ETH_TX_BUF_SIZE - ipBUFFER_PADDING ) { - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) - { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 20U ) ) != pdFALSE ) - { - xReleaseAfterSend = pdFALSE; - if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) - { - xResult = pdPASS; - } + /* TODO: uncomment this after chaining Tx Buffers */ + /* if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { */ + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 20U ) ) != pdFALSE ) + { + xReleaseAfterSend = pdFALSE; + if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) + { + xResult = pdPASS; + } else { configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); } - xSemaphoreGive( xTxMutex ); - } - } + xSemaphoreGive( xTxMutex ); + } + /* TODO: uncomment this after chaining Tx Buffers */ + /* else + { + xSemaphoreGive( xTxDescSem ); + } + } */ } } if( xReleaseAfterSend != pdFALSE ) - { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); - } + { + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } } return xResult; @@ -352,11 +425,11 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript static BaseType_t prvNetworkInterfaceInput( void ) { /* TODO: ipconfigZERO_COPY_RX_DRIVER */ - BaseType_t xResult = 0; + BaseType_t xResult = 0; NetworkBufferDescriptor_t * pStartDescriptor = NULL; - while ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pStartDescriptor ) == HAL_OK ) - { - xResult++; + while ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pStartDescriptor ) == HAL_OK ) + { + xResult++; if ( pStartDescriptor != NULL ) { const IPStackEvent_t xRxEvent = { @@ -368,8 +441,7 @@ static BaseType_t prvNetworkInterfaceInput( void ) { iptraceETHERNET_RX_EVENT_LOST(); NetworkBufferDescriptor_t * pxDescriptorToClear = pStartDescriptor; - do - { + do { #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; #else @@ -380,10 +452,10 @@ static BaseType_t prvNetworkInterfaceInput( void ) } while( pxDescriptorToClear != NULL ); } } - } + } configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); - return ( BaseType_t ) ( xResult > 0 ); + return ( BaseType_t ) ( xResult > 0 ); } /*-----------------------------------------------------------*/ @@ -394,7 +466,7 @@ static void prvEMACHandlerTask( void * pvParameters ) for( ;; ) { - BaseType_t xResult = 0U; + BaseType_t xResult = 0U; uint32_t ulISREvents = 0U; @@ -409,14 +481,24 @@ static void prvEMACHandlerTask( void * pvParameters ) if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { iptraceNETWORK_INTERFACE_TRANSMIT(); - configASSERT( HAL_ETH_ReleaseTxPacket( heth ) == HAL_OK ); + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { + HAL_StatusTypeDef xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + xSemaphoreGive( xTxMutex ); + } } if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) { + /* TODO: Does this recover from fatal bus error? */ HAL_ETH_Stop_IT( &xEthHandle ); /* FreeRTOS_NetworkDown() - HAL_ETH_ReleaseTxPacket( &xEthHandle );*/ + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { + configASSERT( HAL_ETH_ReleaseTxPacket( &xEthHandle ) == HAL_OK ); + xSemaphoreGive( xTxMutex ); + }*/ HAL_ETH_Start_IT( &xEthHandle ); } } @@ -432,87 +514,92 @@ static void prvEMACHandlerTask( void * pvParameters ) static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ) { - uint32_t pErrorCode = 0; - HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); - if ( pErrorCode != 0 ) - { - return pdFALSE; - } + BaseType_t xResult = pdFALSE; - const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; - - #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) - switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) + do { + uint32_t pErrorCode = 0; + HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); + configASSERT( xHalResult == HAL_OK ); + if ( pErrorCode != 0 ) { - case ipARP_FRAME_TYPE: - return pdTRUE; + break; + } - case ipIPv4_FRAME_TYPE: - break; + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; - default: - return pdFALSE; - } - #endif + const uint16_t usFrameType = pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType; - #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) - const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + if( usFrameType != ipARP_FRAME_TYPE && usFrameType != ipIPv4_FRAME_TYPE) + { + break; + } + #endif + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) + if( usFrameType == ipIPv4_FRAME_TYPE ) + { + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); - if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) - { - return pdFALSE; - } + if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) + { + break; + } - if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) - { - return pdFALSE; - } + if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) + { + break; + } - const uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; + const uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; - if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) && ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) - { - return pdFALSE; - } + if( ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) && ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) ) + { + break; + } - if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) - { - if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )) - { - return pdFALSE; + if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) + { + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )) + { + break; + } + /* TODO: uncomment these & test */ + /*#if ipconfigUSE_LLMNR == 1 + && ( usDestinationPort != ipLLMNR_PORT ) && + ( usSourcePort != ipLLMNR_PORT ) + #endif + #if ipconfigUSE_MDNS == 1 + && ( usDestinationPort != ipMDNS_PORT ) && + ( usSourcePort != ipMDNS_PORT ) + #endif + #if ipconfigUSE_NBNS == 1 + && ( usDestinationPort != ipNBNS_PORT ) && + ( usSourcePort != ipNBNS_PORT ) + #endif + #if ipconfigUSE_DNS == 1 + && ( usSourcePort != ipDNS_PORT ) + #endif + )*/ + } } - /*#if ipconfigUSE_LLMNR == 1 - && ( usDestinationPort != ipLLMNR_PORT ) && - ( usSourcePort != ipLLMNR_PORT ) - #endif - #if ipconfigUSE_MDNS == 1 - && ( usDestinationPort != ipMDNS_PORT ) && - ( usSourcePort != ipMDNS_PORT ) - #endif - #if ipconfigUSE_NBNS == 1 - && ( usDestinationPort != ipNBNS_PORT ) && - ( usSourcePort != ipNBNS_PORT ) - #endif - #if ipconfigUSE_DNS == 1 - && ( usSourcePort != ipDNS_PORT ) - #endif - )*/ - } - #endif + #endif + + xResult = pdTRUE; + } while( ipFALSE_BOOL ); - return pdTRUE; + return xResult; } /*-----------------------------------------------------------*/ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - BaseType_t iResult = -1; - if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) - { - iResult = 0; - } - return iResult; + BaseType_t iResult = -1; + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + { + iResult = 0; + } + return iResult; } /*-----------------------------------------------------------*/ @@ -531,36 +618,35 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static void prvEthernetUpdateConfig( void ) { + BaseType_t xPhyResult; + HAL_StatusTypeDef xHalResult; + /* TODO: xEthHandle.gState == Check HAL_ETH_STATE_STARTED */ + if( xGetPhyLinkStatus() != pdFAIL ) { - /* TODO: if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE ) */ - configASSERT( xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ) == 0 ); + ETH_MACConfigTypeDef MACConf; + xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); + configASSERT( xHalResult == HAL_OK ); - ETH_MACConfigTypeDef MACConf; - configASSERT( HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ) == HAL_OK ); + #if ( ipconfigETHERNET_AN_ENABLE != 0 ) + xPhyResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + configASSERT( xPhyResult == 0 ); - if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) - { - MACConf.DuplexMode = ETH_FULLDUPLEX_MODE; - } - else - { - MACConf.DuplexMode = ETH_HALFDUPLEX_MODE; - } + MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; - if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) - { - MACConf.Speed = ETH_SPEED_10M; - } - else - { - MACConf.Speed = ETH_SPEED_100M; - } + xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); + configASSERT( xHalResult == HAL_OK ); + #else + xPhyObject.xPhyPreferences.ucDuplex = ( MACConf.DuplexMode == ETH_FULLDUPLEX_MODE ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + xPhyObject.xPhyPreferences.ucSpeed = ( MACConf.Speed == ETH_SPEED_10M ) ? PHY_SPEED_10 : PHY_SPEED_100; + xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO; + xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #endif - configASSERT( HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ) == HAL_OK ); if( xGetPhyLinkStatus() != pdFAIL ) { - HAL_ETH_Start_IT( &xEthHandle ); + ( void ) HAL_ETH_Start_IT( &xEthHandle ); } } else @@ -568,8 +654,13 @@ static void prvEthernetUpdateConfig( void ) if( HAL_ETH_Stop_IT( &xEthHandle ) == HAL_OK ) { /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ - configASSERT( HAL_ETH_ReleaseTxPacket( &xEthHandle ) == HAL_OK ); - memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + { + xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + ( void ) xSemaphoreGive( xTxMutex ); + } } } } @@ -611,9 +702,9 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) const size_t uxTxUsed = heth->TxDescList.BuffersInUse; if( uxMostTXDescsUsed < uxTxUsed ) - { - uxMostTXDescsUsed = uxTxUsed; - } + { + uxMostTXDescsUsed = uxTxUsed; + } BaseType_t xHigherPriorityTaskWoken = pdFALSE; xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); @@ -641,7 +732,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { /* F7 - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ /* H7 - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ - /* TODO: Check if allocated in HAL_ETH_RxAllocateCallback before error interrupt, then release here */ + /* TODO: Check if allocated in HAL_ETH_RxAllocateCallback before error interrupt, then release in task */ /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_RBU ) == ETH_DMACSR_RBU ) { @@ -649,7 +740,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) /* TODO: same as above but for Tx */ /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) { - xSemaphoreGiveFromISR( xTxMutex ); xSemaphoreGiveFromISR( xTxDescSem ); }*/ } @@ -671,42 +761,46 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) void HAL_ETH_RxAllocateCallback( uint8_t **buff ) { - NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, pdMS_TO_TICKS( 20U ) ); - if( pxBufferDescriptor != NULL ) - { - *buff = pxBufferDescriptor->pucEthernetBuffer; - } + /* TODO: Verify this size */ + NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, pdMS_TO_TICKS( 20U ) ); + if( pxBufferDescriptor != NULL ) + { + *buff = pxBufferDescriptor->pucEthernetBuffer; + } } /*-----------------------------------------------------------*/ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) { - NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); - if ( prvAcceptPacket( pxCurDescriptor->pucEthernetBuffer ) == pdTRUE ) - { - NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; - NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; - - pxCurDescriptor->xDataLength = Length; - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - pxCurDescriptor->pxNextBuffer = NULL; - #endif - if( *pStartDescriptor == NULL ) + NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); + if( pxCurDescriptor != NULL ) + { + if ( prvAcceptPacket( pxCurDescriptor->pucEthernetBuffer ) == pdTRUE ) { - *pStartDescriptor = pxCurDescriptor; - } - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - else if( pEndDescriptor != NULL ) + NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; + NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; + + pxCurDescriptor->xDataLength = Length; + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + pxCurDescriptor->pxNextBuffer = NULL; + #endif + if( *pStartDescriptor == NULL ) { - ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; + *pStartDescriptor = pxCurDescriptor; } - #endif - *pEndDescriptor = pxCurDescriptor; - } - else - { - vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + else if( pEndDescriptor != NULL ) + { + ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; + } + #endif + *pEndDescriptor = pxCurDescriptor; + } + else + { + vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); + } } } @@ -714,12 +808,10 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t void HAL_ETH_TxFreeCallback( uint32_t *buff ) { - NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; - if( pxNetworkBuffer != NULL ) - { - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - } - xSemaphoreGive( xTxDescSem ); + NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + /* TODO: uncomment this after chaining Tx Buffers */ + /* xSemaphoreGive( xTxDescSem ); */ } /*-----------------------------------------------------------*/ From dffe26767edb479856fa536269b64529d6e67285 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 23 Jul 2023 21:57:20 -0400 Subject: [PATCH 05/68] update to 4.0.0 compatibility --- .../portable/NetworkInterface/CMakeLists.txt | 3 +- .../NetworkInterface/STM32/CMakeLists.txt | 20 + .../NetworkInterface/STM32/NetworkInterface.c | 994 ++++++++++-------- 3 files changed, 594 insertions(+), 423 deletions(-) create mode 100644 source/portable/NetworkInterface/STM32/CMakeLists.txt diff --git a/source/portable/NetworkInterface/CMakeLists.txt b/source/portable/NetworkInterface/CMakeLists.txt index dcf98604dd..923e0cccb2 100644 --- a/source/portable/NetworkInterface/CMakeLists.txt +++ b/source/portable/NetworkInterface/CMakeLists.txt @@ -45,8 +45,7 @@ add_subdirectory(mw300_rd) add_subdirectory(pic32mzef) add_subdirectory(RX) add_subdirectory(SH2A) -add_subdirectory(STM32Fxx) -add_subdirectory(STM32Hxx) +add_subdirectory(STM32) add_subdirectory(ThirdParty/MSP432) add_subdirectory(TM4C) add_subdirectory(WinPCap) diff --git a/source/portable/NetworkInterface/STM32/CMakeLists.txt b/source/portable/NetworkInterface/STM32/CMakeLists.txt new file mode 100644 index 0000000000..4d019b1c28 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/CMakeLists.txt @@ -0,0 +1,20 @@ +if (NOT ( (FREERTOS_PLUS_TCP_NETWORK_IF STREQUAL "STM32") ) ) + return() +endif() + +#------------------------------------------------------------------------------ +add_library( freertos_plus_tcp_network_if STATIC ) + +target_sources( freertos_plus_tcp_network_if + PRIVATE + NetworkInterface.c +) + +target_link_libraries( freertos_plus_tcp_network_if + PUBLIC + freertos_plus_tcp_port + freertos_plus_tcp_network_if_common + PRIVATE + freertos_kernel + freertos_plus_tcp +) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 1cf79a7276..4f36d20553 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -49,13 +49,13 @@ #include "phyHandling.h" /* ST includes. */ -#if defined(STM32F4) +#if defined( STM32F4 ) #include "stm32f4xx_hal_eth.h" -#elif defined(STM32F7) +#elif defined( STM32F7 ) #include "stm32f7xx_hal_eth.h" -#elif defined(STM32H7) +#elif defined( STM32H7 ) #include "stm32h7xx_hal_eth.h" -#elif defined(STM32H5) +#elif defined( STM32H5 ) /* Untested */ #include "stm32h5xx_hal_eth.h" #else @@ -64,59 +64,53 @@ /*-----------------------------------------------------------*/ -/* TODO: Should these be moved to FreeRTOSIPConfigDefaults.h? */ -#ifndef ipconfigETHERNET_AN_ENABLE - #define ipconfigETHERNET_AN_ENABLE 1 -#endif - -#if ( ipconfigETHERNET_AN_ENABLE == 0 ) - #ifndef ipconfigETHERNET_USE_100MB - #define ipconfigETHERNET_USE_100MB 1 - #endif - - #ifndef ipconfigETHERNET_USE_FULL_DUPLEX - #define ipconfigETHERNET_USE_FULL_DUPLEX 1 - #endif -#endif - -#ifndef ipconfigETHERNET_AUTO_CROSS_ENABLE - #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1 -#endif - -#if ( ipconfigETHERNET_AUTO_CROSS_ENABLE == 0 ) - #ifndef ipconfigETHERNET_CROSSED_LINK - #define ipconfigETHERNET_CROSSED_LINK 0 - #endif -#endif - -#ifndef ipconfigUSE_RMII - #define ipconfigUSE_RMII 1 +/* TODO: This should be made moved from FreeRTOS_IP.c to FreeRTOS_IP_Private.h + * so that all the network interfaces don't have to keep defining it. */ +#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #endif /*-----------------------------------------------------------*/ -/* TODO: Verify this size */ -#define NETWORK_BUFFER_SIZE ( ( ( ETH_RX_BUF_SIZE + ipBUFFER_PADDING ) + 7 ) & ~0x7UL ) +#define EMAC_DATA_BUFFER_SIZE ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) +#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + 31U ) & ~0x1FuL ) -#define EMAC_IF_RX_EVENT 1UL -#define EMAC_IF_TX_EVENT 2UL -#define EMAC_IF_ERR_EVENT 4UL -#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_ERR_EVENT ) +#define EMAC_IF_RX_EVENT 1UL +#define EMAC_IF_TX_EVENT 2UL +#define EMAC_IF_TX_ERR_EVENT 4UL +#define EMAC_IF_RX_ERR_EVENT 8UL +#define EMAC_IF_DMA_ERR_EVENT 16UL +#define EMAC_IF_ETH_ERR_EVENT 32UL +#define EMAC_IF_MAC_ERR_EVENT 64UL +#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_TX_ERR_EVENT | EMAC_IF_RX_ERR_EVENT | EMAC_IF_DMA_ERR_EVENT | EMAC_IF_ETH_ERR_EVENT | EMAC_IF_MAC_ERR_EVENT ) typedef enum { - eMACInit, - eMACPass, - eMACFailed + eMACEthInit, + eMACPhyInit, + eMACPhyStart, + eMACTaskStart, + eMACEthStart, + eMACInitComplete } eMAC_INIT_STATUS_TYPE; /*-----------------------------------------------------------*/ -static BaseType_t prvNetworkInterfaceInput( void ); +static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ); + +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); + +static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); -static void prvEMACHandlerTask( void * pvParameters ) __attribute__((__noreturn__)); +static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); -static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ); +static UBaseType_t prvNetworkInterfaceInput( void ); + +static void prvEMACHandlerTask( void * pvParameters ) __attribute__( ( __noreturn__ ) ); + +static BaseType_t prvAcceptPacket( NetworkBufferDescriptor_t * pxDescriptor ); static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); @@ -124,74 +118,46 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static void prvEthernetUpdateConfig( void ); -/*-----------------------------------------------------------*/ +/* static void prvMACAddressConfig( ETH_HandleTypeDef * heth, uint32_t ulIndex, uint8_t * Addr ); */ -static ETH_HandleTypeDef xEthHandle; +#if ( ipconfigIPv4_BACKWARD_COMPATIBLE != 0 ) + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) + { + return pxSTM32_FillInterfaceDescriptor( xEMACIndex, pxInterface ); + } +#endif -static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ) ) ); +/*-----------------------------------------------------------*/ -/* TODO: implement ( ipconfigZERO_COPY_RX_DRIVER == 0 ) */ -/*#if ( ipconfigZERO_COPY_RX_DRIVER == 0 ) - __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RX_DESC_CNT ][ ETH_RX_BUF_SIZE ] __ALIGN_END; -#endif*/ +static ETH_HandleTypeDef xEthHandle; -static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ) ) ); +static ETH_MACConfigTypeDef xMACConfig; -/* TODO: implement ( ipconfigZERO_COPY_TX_DRIVER == 0 ) */ -/*#if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) - __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TX_DESC_CNT ][ ETH_TX_BUF_SIZE ] __ALIGN_END; -#endif*/ +static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ), aligned( 4 ) ) ); -static ETH_TxPacketConfig xTxConfig; +static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ), aligned( 4 ) ) ); -/* TODO: implement ( ipconfigUSE_LLMNR != 0 ) */ -/*#if ( ipconfigUSE_LLMNR != 0 ) - static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; -#endif*/ +static NetworkInterface_t * pxMyInterface = NULL; static TaskHandle_t xEMACTaskHandle; static SemaphoreHandle_t xTxMutex; -/* TODO: uncomment this after chaining Tx Buffers */ -/* xTxDescSem is not useful unless xTxBuffer.next != NULL */ -/* static SemaphoreHandle_t xTxDescSem; */ +static SemaphoreHandle_t xTxDescSem; static EthernetPhy_t xPhyObject; -static const PhyProperties_t xPHYProperties = -{ - #if ( ipconfigETHERNET_AN_ENABLE != 0 ) - .ucSpeed = PHY_SPEED_AUTO, - .ucDuplex = PHY_DUPLEX_AUTO, - #else - #if ( ipconfigETHERNET_USE_100MB != 0 ) - .ucSpeed = PHY_SPEED_100, - #else - .ucSpeed = PHY_SPEED_10, - #endif - - #if ( ipconfigETHERNET_USE_FULL_DUPLEX != 0 ) - .ucDuplex = PHY_DUPLEX_FULL, - #else - .ucDuplex = PHY_DUPLEX_HALF, - #endif - #endif - - #if ( ipconfigETHERNET_AN_ENABLE != 0 ) && ( ipconfigETHERNET_AUTO_CROSS_ENABLE != 0 ) - .ucMDI_X = PHY_MDIX_AUTO, - #elif ( ipconfigETHERNET_CROSSED_LINK != 0 ) - .ucMDI_X = PHY_MDIX_CROSSED, - #else - .ucMDI_X = PHY_MDIX_DIRECT, - #endif +static const PhyProperties_t xPHYProperties = { + .ucSpeed = PHY_SPEED_AUTO, + .ucDuplex = PHY_DUPLEX_AUTO, + .ucMDI_X = PHY_MDIX_AUTO, }; /*-----------------------------------------------------------*/ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ NETWORK_BUFFER_SIZE ] __attribute__( ( aligned( 4 ), section( ".EthBuffersSection" ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __attribute__( ( section( ".EthBuffersSection" ), aligned( 32 ) ) ); for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) { @@ -202,8 +168,10 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB /*-----------------------------------------------------------*/ -BaseType_t xGetPhyLinkStatus( void ) +static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) { + ( void ) pxInterface; + BaseType_t xReturn = pdFAIL; if( xPhyObject.ulLinkStatusMask != 0U ) @@ -213,166 +181,278 @@ BaseType_t xGetPhyLinkStatus( void ) return xReturn; } + /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceInitialise( void ) +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { - BaseType_t xResult = pdFAIL; - BaseType_t xPhyResult; + static char pcName[ 17 ]; + + snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); + + memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; + pxInterface->pvArgument = ( void * ) xEMACIndex; + pxInterface->pfInitialise = xSTM32_NetworkInterfaceInitialise; + pxInterface->pfOutput = xSTM32_NetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = xSTM32_GetPhyLinkStatus; + + FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxInterface; +} + +/*-----------------------------------------------------------*/ + +static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) +{ + BaseType_t xInitResult = pdFAIL; + BaseType_t xResult; HAL_StatusTypeDef xHalResult; + NetworkEndPoint_t * pxEndPoint; + /* BaseType_t xMACEntry = ETH_MAC_ADDRESS1; */ /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; + static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACEthInit; - if( xMacInitStatus == eMACInit ) + switch( xMacInitStatus ) { - if( xEMACTaskHandle == NULL ) - { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - static StaticSemaphore_t xTxMutexBuf; - xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); - - /* TODO: uncomment this after chaining Tx Buffers */ - /* static StaticSemaphore_t xTxDescSemBuf; - xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); */ - - static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; - static StaticTask_t xEMACTaskTCB; - /* TODO: Allow stack size & priority to be defined */ - xEMACTaskHandle = xTaskCreateStatic( - prvEMACHandlerTask, - "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), - NULL, - ( configMAX_PRIORITIES - 1 ), - uxEMACTaskStack, - &xEMACTaskTCB - ); - #else - xTxMutex = xSemaphoreCreateMutex(); - - /* TODO: uncomment this after chaining Tx Buffers */ - /*xTxDescSem = xSemaphoreCreateCounting( - ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, - ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS - );*/ - - /* TODO: Allow stack size & priority to be defined */ - ( void ) xTaskCreate( - prvEMACHandlerTask, - "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), - NULL, - ( configMAX_PRIORITIES - 1 ), - &xEMACTaskHandle - ); - #endif - configASSERT( xTxMutex ); - vQueueAddToRegistry( xTxMutex, "TXMutex" ); + default: + configASSERT( pdFALSE ); + break; - /* TODO: uncomment this after chaining Tx Buffers */ - /*configASSERT( xTxDescSem ); - vQueueAddToRegistry( xTxDescSem, "xTxDescSem" );*/ + case eMACEthInit: + pxMyInterface = pxInterface; - configASSERT( xEMACTaskHandle ); - } + pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + configASSERT( pxEndPoint != NULL ); - if( xEthHandle.Instance == NULL ) - { xEthHandle.Instance = ETH; - xEthHandle.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); - xEthHandle.Init.MediaInterface = ( ipconfigUSE_RMII != 0 ) ? HAL_ETH_RMII_MODE : HAL_ETH_MII_MODE; + xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; /* FreeRTOS_GetMACAddress(); */ + xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; xEthHandle.Init.TxDesc = DMATxDscrTab; xEthHandle.Init.RxDesc = DMARxDscrTab; - /* TODO: Verify RxBuffLen size */ - xEthHandle.Init.RxBuffLen = ETH_RX_BUF_SIZE; + xEthHandle.Init.RxBuffLen = EMAC_DATA_BUFFER_SIZE; memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); - #if defined(STM32F7) || defined(STM32F4) + #if defined( STM32F7 ) || defined( STM32F4 ) /* This function doesn't get called in Fxx driver */ HAL_ETH_SetMDIOClockRange( &xEthHandle ); #endif xHalResult = HAL_ETH_Init( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); + if( xHalResult != HAL_OK ) + { + break; + } configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - /* TODO: uncomment & test these */ - /*#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) - BaseType_t xMACEntry = ETH_MAC_ADDRESS1; - uint8_t pMACAddr[6]; - memset( &pMACAddr, 0, sizeof( pMACAddr ) ); - xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, pMACAddr ); - configASSERT( xHalResult == HAL_OK ); - #endif + xMacInitStatus = eMACPhyInit; + /* Fallthrough */ - #if ( ipconfigUSE_MDNS != 0 ) - xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xMDNS_MACAddressIPv4 ); - configASSERT( xHalResult == HAL_OK ); - xMACEntry += 8; - #endif - #if ( ipconfigUSE_LLMNR != 0 ) - xHalResult = HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, xMACEntry, ( uint8_t * ) xLLMNR_MACAddress ); + case eMACPhyInit: + vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); + + xResult = xPhyDiscover( &xPhyObject ); + if( xResult == 0 ) + { + break; + } + + xResult = xPhyConfigure( &xPhyObject, &xPHYProperties ); + if( xResult != 0 ) + { + break; + } + + xMacInitStatus = eMACPhyStart; + /* Fallthrough */ + + case eMACPhyStart: + if ( xSTM32_GetPhyLinkStatus( pxInterface ) == pdFAIL ) + { + xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ + configASSERT( xResult == 0 ); + if ( xSTM32_GetPhyLinkStatus( pxMyInterface ) == pdFAIL ) + { + break; + } + } + + xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); + configASSERT( xHalResult == HAL_OK ); + if( xHalResult != HAL_OK ) + { + break; + } + xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + xMACConfig.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); + xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &xMACConfig ); + configASSERT( xHalResult == HAL_OK ); + if( xHalResult != HAL_OK ) + { + break; + } + + xMacInitStatus = eMACTaskStart; + /* Fallthrough */ + + case eMACTaskStart: + if( xTxMutex == NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + { + static StaticSemaphore_t xTxMutexBuf; + xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + } + #else + xTxMutex = xSemaphoreCreateMutex(); + #endif + configASSERT( xTxMutex != NULL ); + if( xTxMutex == NULL ) + { + break; + } + vQueueAddToRegistry( xTxMutex, "TXMutex" ); + } + + if( xTxDescSem == NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + { + static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); + } + #else + xTxDescSem = xSemaphoreCreateCounting( + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, + ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + ); + #endif + configASSERT( xTxDescSem != NULL ); + if( xTxDescSem == NULL ) + { + break; + } + vQueueAddToRegistry( xTxDescSem, "xTxDescSem" ); + } + + if( xEMACTaskHandle == NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + { + static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; + static StaticTask_t xEMACTaskTCB; + xEMACTaskHandle = xTaskCreateStatic( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + uxEMACTaskStack, + &xEMACTaskTCB + ); + } + #else + xResult = xTaskCreate( + prvEMACHandlerTask, + "EMAC", + ( 2 * configMINIMAL_STACK_SIZE ), + NULL, + ( configMAX_PRIORITIES - 1 ), + &xEMACTaskHandle + ); + configASSERT( xResult == pdPASS ); + #endif + configASSERT( xEMACTaskHandle != NULL ); + if( xEMACTaskHandle == NULL ) + { + break; + } + } + + xMacInitStatus = eMACEthStart; + /* Fallthrough */ + + case eMACEthStart: + if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) + { + xHalResult = HAL_ETH_Start_IT( &xEthHandle ); configASSERT( xHalResult == HAL_OK ); - xMACEntry += 8; - #endif*/ - - memset( &xTxConfig, 0, sizeof( xTxConfig ) ); - xTxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD; - xTxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; - #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) - xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; - xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; - #else - xTxConfig.ChecksumCtrl = ETH_CHECKSUM_DISABLE; - #endif - xMacInitStatus = eMACPass; - } - } + if( xHalResult != HAL_OK ) + { + break; + } + } + configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); + configASSERT( xEthHandle.RxDescList.ItMode == 1U); - if( xMacInitStatus == eMACPass ) - { - vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); - xPhyResult = xPhyDiscover( &xPhyObject ); - configASSERT( xPhyResult > 0 ); - xPhyResult = xPhyConfigure( &xPhyObject, &xPHYProperties ); - configASSERT( xPhyResult == 0 ); - xPhyResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - configASSERT( xPhyResult == 0 ); - } + xMacInitStatus = eMACInitComplete; + /* Fallthrough */ - if ( xGetPhyLinkStatus() != pdFAIL ) - { - ETH_MACConfigTypeDef MACConf; - xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); - configASSERT( xHalResult == HAL_OK ); - MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; - MACConf.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); - xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); - configASSERT( xHalResult == HAL_OK ); - xHalResult = HAL_ETH_Start_IT( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); - xResult = pdPASS; + case eMACInitComplete: + configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); + xInitResult = pdPASS; } - return xResult; + return xInitResult; } /*-----------------------------------------------------------*/ -BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; - /* TODO: ipconfigZERO_COPY_TX_DRIVER */ + configASSERT( pxDescriptor != NULL ); + /* Zero-Copy Only */ + configASSERT( xReleaseAfterSend != pdFALSE ); - if( pxDescriptor != NULL ) + if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= EMAC_DATA_BUFFER_SIZE ) ) { - if( xGetPhyLinkStatus() != pdFAIL ) + if( xSTM32_GetPhyLinkStatus( pxInterface ) != pdFAIL ) { - /* TODO: Tx Optimization by setting .next? */ + static ETH_TxPacketConfig xTxConfig = { + .CRCPadCtrl = ETH_CRC_PAD_INSERT, + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, + .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, + #else + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, + .ChecksumCtrl = ETH_CHECKSUM_DISABLE, + #endif + }; + + /*ETH_BufferTypeDef xTxBuffer[ ETH_TX_DESC_CNT ]; + memset( &xTxBuffer, 0, sizeof( xTxBuffer ) ); + NetworkBufferDescriptor_t * pxCurDescriptor = pxDescriptor; + xTxConfig.Length = 0; + for( size_t i = 0; i < ETH_TX_DESC_CNT; i++ ) + { + if( pxCurDescriptor == NULL ) + { + break; + } + xTxBuffer[ i ].buffer = ( uint8_t * ) pxCurDescriptor->pucEthernetBuffer; + xTxBuffer[ i ].len = pxCurDescriptor->xDataLength; + xTxConfig.Length += pxCurDescriptor->xDataLength; + if( i > 0 ) + { + xTxBuffer[ i - 1 ].next = &xTxBuffer[ i ]; + } + if( pxCurDescriptor->pxNextBuffer == NULL ) + { + xTxBuffer[ i ].next = NULL; + } + pxCurDescriptor = pxDescriptor->pxNextBuffer; + } + + xTxConfig.TxBuffer = xTxBuffer; + xTxConfig.pData = pxDescriptor;*/ + ETH_BufferTypeDef xTxBuffer = { .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, .len = pxDescriptor->xDataLength, @@ -383,78 +463,138 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.pData = pxDescriptor; - if( xTxConfig.Length <= ETH_TX_BUF_SIZE - ipBUFFER_PADDING ) + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 200U ) ) != pdFALSE ) { - /* TODO: uncomment this after chaining Tx Buffers */ - /* if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) - { */ - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 20U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 50U ) ) != pdFALSE ) + { + HAL_StatusTypeDef xHalResult = HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ); + xSemaphoreGive( xTxMutex ); + if( xHalResult == HAL_OK ) { + /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ xReleaseAfterSend = pdFALSE; - if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) + xResult = pdPASS; + } + else + { + xSemaphoreGive( xTxDescSem ); + configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); + if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) { - xResult = pdPASS; + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Eth Not Started\n" ) ); } - else + if( xEthHandle.ErrorCode & HAL_ETH_ERROR_BUSY ) { - configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); + HAL_ETH_ReleaseTxPacket( &xEthHandle ); } - xSemaphoreGive( xTxMutex ); } - /* TODO: uncomment this after chaining Tx Buffers */ - /* else - { - xSemaphoreGive( xTxDescSem ); - } - } */ + } + else + { + xSemaphoreGive( xTxDescSem ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); + } + } + else + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); } } - - if( xReleaseAfterSend != pdFALSE ) + else { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); } } + else + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Buffer\n" ) ); + } + + if( xReleaseAfterSend != pdFALSE ) + { + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + + /*if( xResult == pdFAIL ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Failed\n" ) ); + xTaskNotify( xEMACTaskHandle, EMAC_IF_TX_ERR_EVENT, eSetBits ); + }*/ return xResult; } /*-----------------------------------------------------------*/ -static BaseType_t prvNetworkInterfaceInput( void ) +static UBaseType_t prvNetworkInterfaceInput( void ) { - /* TODO: ipconfigZERO_COPY_RX_DRIVER */ - BaseType_t xResult = 0; - NetworkBufferDescriptor_t * pStartDescriptor = NULL; - while ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pStartDescriptor ) == HAL_OK ) + UBaseType_t xResult = 0; + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + NetworkBufferDescriptor_t * pxStartDescriptor = NULL; + NetworkBufferDescriptor_t * pxEndDescriptor = NULL; + #endif + NetworkBufferDescriptor_t * pxCurDescriptor = NULL; + IPStackEvent_t xRxEvent = { + .eEventType = eNetworkRxEvent, + .pvData = NULL + }; + while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) { + /*configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE );*/ xResult++; - if ( pStartDescriptor != NULL ) - { - const IPStackEvent_t xRxEvent = { - .eEventType = eNetworkRxEvent, - .pvData = ( void * ) pStartDescriptor - }; + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + if ( pxStartDescriptor == NULL ) + { + pxStartDescriptor = pxCurDescriptor; + } + else if ( pxEndDescriptor != NULL ) + { + pxEndDescriptor->pxNextBuffer = pxCurDescriptor; + } + pxEndDescriptor = pxCurDescriptor; + #else + xRxEvent.pvData = ( void * ) pxCurDescriptor; + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 20U ) != pdPASS ) + { + iptraceETHERNET_RX_EVENT_LOST(); + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); + vReleaseNetworkBufferAndDescriptor( pxStartDescriptor ); + } + #endif + } + - if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 0U ) != pdPASS ) + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + if( xResult > 0 ) + { + pxStartDescriptor->pxInterface = pxMyInterface; + pxStartDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxStartDescriptor->pucEthernetBuffer ); + xRxEvent.pvData = ( void * ) pxStartDescriptor; + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 100U ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); - NetworkBufferDescriptor_t * pxDescriptorToClear = pStartDescriptor; + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); + NetworkBufferDescriptor_t * pxDescriptorToClear = pxStartDescriptor; do { - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; - #else - NetworkBufferDescriptor_t * pxNext = NULL; - #endif + NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); pxDescriptorToClear = pxNext; } while( pxDescriptorToClear != NULL ); } } + #endif + + if( xResult == 0 ) + { + xTaskNotify( xEMACTaskHandle, EMAC_IF_RX_ERR_EVENT, eSetBits ); } + configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); + if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) + { + xTaskNotify( xEMACTaskHandle, EMAC_IF_ETH_ERR_EVENT, eSetBits ); + } return ( BaseType_t ) ( xResult > 0 ); } @@ -467,125 +607,129 @@ static void prvEMACHandlerTask( void * pvParameters ) for( ;; ) { BaseType_t xResult = 0U; - uint32_t ulISREvents = 0U; - if ( xTaskNotifyWait( 0U, EMAC_IF_ALL_EVENT, &ulISREvents, pdMS_TO_TICKS( 500UL ) ) == pdTRUE ) + if ( xTaskNotifyWait( 0U, EMAC_IF_ALL_EVENT, &ulISREvents, pdMS_TO_TICKS( 100UL ) ) == pdTRUE ) { + HAL_StatusTypeDef xHalResult; + if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) { iptraceNETWORK_INTERFACE_RECEIVE(); - xResult = prvNetworkInterfaceInput(); + xResult = ( prvNetworkInterfaceInput() > 0 ); } if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { iptraceNETWORK_INTERFACE_TRANSMIT(); - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) { - HAL_StatusTypeDef xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); configASSERT( xHalResult == HAL_OK ); xSemaphoreGive( xTxMutex ); } } + if( ( ulISREvents & EMAC_IF_TX_ERR_EVENT ) != 0 ) + { + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) + { + xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > xEthHandle.TxDescList.BuffersInUse ) + { + xSemaphoreGive( xTxDescSem ); + } + } + } + + if( ( ulISREvents & EMAC_IF_RX_ERR_EVENT ) != 0 ) + { + /*do { + xResult = ( prvNetworkInterfaceInput() > 0 ); + } while ( xResult != pdFALSE ); + xResult = pdTRUE;*/ + } + + if( ( ulISREvents & EMAC_IF_ETH_ERR_EVENT ) != 0 ) + { + /* xEthHandle.gState */ + /* xEthHandle.ErrorCode */ + } + + if( ( ulISREvents & EMAC_IF_MAC_ERR_EVENT ) != 0 ) + { + /* xEthHandle.MACErrorCode */ + } - if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) + if( ( ulISREvents & EMAC_IF_DMA_ERR_EVENT ) != 0 ) { /* TODO: Does this recover from fatal bus error? */ - HAL_ETH_Stop_IT( &xEthHandle ); - /* FreeRTOS_NetworkDown() - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 5000U ) ) != pdFALSE ) { - configASSERT( HAL_ETH_ReleaseTxPacket( &xEthHandle ) == HAL_OK ); + /* xEthHandle.DMAErrorCode */ + xEthHandle.gState = HAL_ETH_STATE_STARTED; + xHalResult = HAL_ETH_Stop_IT( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); + configASSERT( xEthHandle.RxDescList.ItMode == 0U); + xHalResult = HAL_ETH_DeInit( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_RESET ); + xHalResult = HAL_ETH_Init( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); + xHalResult = HAL_ETH_Start_IT( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); + configASSERT( xEthHandle.RxDescList.ItMode == 1U); xSemaphoreGive( xTxMutex ); - }*/ - HAL_ETH_Start_IT( &xEthHandle ); + } } } - if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) + if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { prvEthernetUpdateConfig(); + + /* + #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) + { + if( xGetPhyLinkStatus() == pdFALSE ) + { + FreeRTOS_NetworkDown(); + } + } + */ } } } /*-----------------------------------------------------------*/ -static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ) +static BaseType_t prvAcceptPacket( NetworkBufferDescriptor_t * pxDescriptor ) { BaseType_t xResult = pdFALSE; - do { - uint32_t pErrorCode = 0; - HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); - configASSERT( xHalResult == HAL_OK ); - if ( pErrorCode != 0 ) + uint32_t pErrorCode = 0; + HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); + configASSERT( xHalResult == HAL_OK ); + /* Fxx - ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT | ETH_DMARXDESC_LC | ETH_DMARXDESC_CE | ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE */ + /* Hxx - ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT | ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE */ + + if ( pErrorCode == 0 ) + { + eFrameProcessingResult_t xFrameProcessingResult = ipCONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); + if( xFrameProcessingResult == eProcessBuffer ) { - break; + xResult = pdTRUE; } - - const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; - - const uint16_t usFrameType = pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType; - - #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) - if( usFrameType != ipARP_FRAME_TYPE && usFrameType != ipIPv4_FRAME_TYPE) - { - break; - } - #endif - #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) - if( usFrameType == ipIPv4_FRAME_TYPE ) - { - const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); - - if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) - { - break; - } - - if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) - { - break; - } - - const uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; - - if( ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) && ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) ) - { - break; - } - - if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) - { - if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE )) - { - break; - } - /* TODO: uncomment these & test */ - /*#if ipconfigUSE_LLMNR == 1 - && ( usDestinationPort != ipLLMNR_PORT ) && - ( usSourcePort != ipLLMNR_PORT ) - #endif - #if ipconfigUSE_MDNS == 1 - && ( usDestinationPort != ipMDNS_PORT ) && - ( usSourcePort != ipMDNS_PORT ) - #endif - #if ipconfigUSE_NBNS == 1 - && ( usDestinationPort != ipNBNS_PORT ) && - ( usSourcePort != ipNBNS_PORT ) - #endif - #if ipconfigUSE_DNS == 1 - && ( usSourcePort != ipDNS_PORT ) - #endif - )*/ - } - } - #endif - - xResult = pdTRUE; - } while( ipFALSE_BOOL ); + else + { + /* Other Enum Values Are Invalid */ + configASSERT( xFrameProcessingResult == eReleaseBuffer ); + } + } return xResult; } @@ -594,79 +738,77 @@ static BaseType_t prvAcceptPacket( const uint8_t * const pucEthernetBuffer ) static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - BaseType_t iResult = -1; + BaseType_t xResult = -1; if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) { - iResult = 0; + xResult = 0; } - return iResult; + return xResult; } /*-----------------------------------------------------------*/ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) { - BaseType_t iResult = -1; + BaseType_t xResult = -1; if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) { - iResult = 0; + xResult = 0; } - return iResult; + return xResult; } /*-----------------------------------------------------------*/ static void prvEthernetUpdateConfig( void ) { - BaseType_t xPhyResult; + BaseType_t xResult; HAL_StatusTypeDef xHalResult; - /* TODO: xEthHandle.gState == Check HAL_ETH_STATE_STARTED */ - if( xGetPhyLinkStatus() != pdFAIL ) + if( xSTM32_GetPhyLinkStatus( pxMyInterface ) != pdFAIL ) { - ETH_MACConfigTypeDef MACConf; - xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &MACConf ); - configASSERT( xHalResult == HAL_OK ); + xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + configASSERT( xResult == 0 ); - #if ( ipconfigETHERNET_AN_ENABLE != 0 ) - xPhyResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - configASSERT( xPhyResult == 0 ); + xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); + configASSERT( xHalResult == HAL_OK ); - MACConf.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - MACConf.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; - xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &MACConf ); - configASSERT( xHalResult == HAL_OK ); - #else - xPhyObject.xPhyPreferences.ucDuplex = ( MACConf.DuplexMode == ETH_FULLDUPLEX_MODE ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - xPhyObject.xPhyPreferences.ucSpeed = ( MACConf.Speed == ETH_SPEED_10M ) ? PHY_SPEED_10 : PHY_SPEED_100; - xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO; - xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - #endif + xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &xMACConfig ); + configASSERT( xHalResult == HAL_OK ); - if( xGetPhyLinkStatus() != pdFAIL ) - { - ( void ) HAL_ETH_Start_IT( &xEthHandle ); - } + xHalResult = HAL_ETH_Start_IT( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); } else { - if( HAL_ETH_Stop_IT( &xEthHandle ) == HAL_OK ) - { - /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 100U ) ) != pdFALSE ) - { - xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); - memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); - ( void ) xSemaphoreGive( xTxMutex ); - } - } + /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ + xHalResult = HAL_ETH_Stop_IT( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); } } /*-----------------------------------------------------------*/ +/*static void prvMACAddressConfig( ETH_HandleTypeDef * heth, uint32_t ulIndex, uint8_t * addr ) +{ + uint32_t ulTempReg; + + ( void ) heth; + + ulTempReg = 0x80000000ul | ( ( uint32_t ) addr[ 5 ] << 8 ) | ( uint32_t ) addr[ 4 ]; + + ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg; + + ulTempReg = ( ( uint32_t ) addr[ 3 ] << 24 ) | ( ( uint32_t ) addr[ 2 ] << 16 ) | ( ( uint32_t ) addr[ 1 ] << 8 ) | addr[ 0 ]; + + ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg; +}*/ + +/*-----------------------------------------------------------*/ + void ETH_IRQHandler( void ) { HAL_ETH_IRQHandler( &xEthHandle ); @@ -685,12 +827,9 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) uxMostRXDescsUsed = uxRxUsed; } - if( xEMACTaskHandle != NULL ) - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } /*-----------------------------------------------------------*/ @@ -707,6 +846,7 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) } BaseType_t xHigherPriorityTaskWoken = pdFALSE; +// vTaskNotifyGiveIndexedFromISR( xEMACTaskHandle, TX_INDEX, &xHigherPriorityTaskWoken ); xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } @@ -715,6 +855,8 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { + // volatile uint32_t errs = heth->Instance->DMASR; + BaseType_t xHigherPriorityTaskWoken = pdFALSE; if( HAL_ETH_GetError( heth ) & HAL_ETH_ERROR_DMA ) { if( HAL_ETH_GetDMAError( heth ) ) @@ -722,85 +864,96 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) if( heth->gState == HAL_ETH_STATE_ERROR ) { /* fatal bus error occurred */ - /* F7 - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ - /* H7 - ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS */ - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + /* Fxx - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ + /* Hxx - ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS */ + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_DMA_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); } else { - /* F7 - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ - /* H7 - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ - /* TODO: Check if allocated in HAL_ETH_RxAllocateCallback before error interrupt, then release in task */ - /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_RBU ) == ETH_DMACSR_RBU ) - { + /* Fxx - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ + /* Hxx - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ + #if defined( STM32F4 ) || defined ( STM32F7 ) + if((HAL_ETH_GetDMAError(heth) & ETH_DMASR_TBUS) == ETH_DMASR_TBUS) + { + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + } - }*/ - /* TODO: same as above but for Tx */ - /*if( ( HAL_ETH_GetDMAError(heth) & ETH_DMACSR_TBU ) == ETH_DMACSR_TBU ) - { - xSemaphoreGiveFromISR( xTxDescSem ); - }*/ + if((HAL_ETH_GetDMAError(heth) & ETH_DMASR_RBUS) == ETH_DMASR_RBUS) + { + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + } + #endif } } } - #ifdef STM32H7 + #if defined( STM32H7 ) || defined ( STM32H5 ) if( HAL_ETH_GetError( heth ) & HAL_ETH_ERROR_MAC ) { if( HAL_ETH_GetMACError( heth ) ) { - + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_MAC_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); } } #endif + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } /*-----------------------------------------------------------*/ void HAL_ETH_RxAllocateCallback( uint8_t **buff ) { - /* TODO: Verify this size */ - NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( ETH_RX_BUF_SIZE, pdMS_TO_TICKS( 20U ) ); + NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( 200U ) ); if( pxBufferDescriptor != NULL ) { *buff = pxBufferDescriptor->pucEthernetBuffer; } + else + { + FreeRTOS_debug_printf( ( "HAL_ETH_RxAllocateCallback: failed\n" ) ); + } } /*-----------------------------------------------------------*/ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) { + NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; + NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); - if( pxCurDescriptor != NULL ) + if ( Length <= EMAC_DATA_BUFFER_SIZE && prvAcceptPacket( pxCurDescriptor ) == pdTRUE ) { - if ( prvAcceptPacket( pxCurDescriptor->pucEthernetBuffer ) == pdTRUE ) + pxCurDescriptor->xDataLength = Length; + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + pxCurDescriptor->pxNextBuffer = NULL; + #endif + if( *pStartDescriptor == NULL ) { - NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; - NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; - - pxCurDescriptor->xDataLength = Length; - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - pxCurDescriptor->pxNextBuffer = NULL; - #endif - if( *pStartDescriptor == NULL ) + *pStartDescriptor = pxCurDescriptor; + } + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + else if( pEndDescriptor != NULL ) { - *pStartDescriptor = pxCurDescriptor; + ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; } + #endif + *pEndDescriptor = pxCurDescriptor; + /* Only single buffer packets are supported */ + configASSERT( *pStartDescriptor == *pEndDescriptor ); + } + else + { + FreeRTOS_debug_printf( ( "HAL_ETH_RxLinkCallback: Buffer Dropped\n" ) ); + NetworkBufferDescriptor_t * pxDescriptorToClear = pxCurDescriptor; + do { #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - else if( pEndDescriptor != NULL ) - { - ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; - } + NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; + #else + NetworkBufferDescriptor_t * pxNext = NULL; #endif - *pEndDescriptor = pxCurDescriptor; - } - else - { - vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); - } + vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); + pxDescriptorToClear = pxNext; + } while( pxDescriptorToClear != NULL ); } } @@ -810,8 +963,7 @@ void HAL_ETH_TxFreeCallback( uint32_t *buff ) { NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - /* TODO: uncomment this after chaining Tx Buffers */ - /* xSemaphoreGive( xTxDescSem ); */ + xSemaphoreGive( xTxDescSem ); } /*-----------------------------------------------------------*/ From eaa7f494368e537ceab48d5f7007b74b6f0313d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 14 Aug 2023 14:31:45 +0200 Subject: [PATCH 06/68] Add STM32 target to Network Interface selection --- CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c6d536a0b..5658b84aad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ set(FREERTOS_PLUS_TCP_NETWORK_IF_LIST POSIX WIN_PCAP # Native Linux & Windows respectively RX SH2A - STM32FXX STM32HXX # ST Micro + STM32 # ST Micro MSP432 TM4C XILINX_ULTRASCALE ZYNQ # AMD/Xilinx @@ -107,8 +107,7 @@ if(NOT FREERTOS_PLUS_TCP_NETWORK_IF IN_LIST FREERTOS_PLUS_TCP_NETWORK_IF_LIST ) " PIC32MZEF_WIFI Target: pic32mzef Wifi Tested: TODO\n" " RX Target: RX Tested: TODO\n" " SH2A Target: SH2A Tested: TODO\n" - " STM32FXX Target: STM32Fxx Tested: TODO\n" - " STM32HXX Target: STM32Hxx Tested: TODO\n" + " STM32 Target: STM32 Tested: TODO\n" " MSP432 Target: MSP432 Tested: TODO\n" " TM4C Target: TM4C Tested: TODO\n" " WIN_PCAP Target: Windows Tested: TODO\n" From 1073648267c4d1b196c28e4a662cf2a5231a363a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Wed, 30 Aug 2023 12:31:57 +0200 Subject: [PATCH 07/68] Fill Interface and EndPoint fields for all Rx Network buffers --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 4f36d20553..a2f6dd582c 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -543,6 +543,8 @@ static UBaseType_t prvNetworkInterfaceInput( void ) { /*configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE );*/ xResult++; + pxCurDescriptor->pxInterface = pxMyInterface; + pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer );; #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if ( pxStartDescriptor == NULL ) { @@ -559,7 +561,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) { iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); - vReleaseNetworkBufferAndDescriptor( pxStartDescriptor ); + vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); } #endif } @@ -568,8 +570,6 @@ static UBaseType_t prvNetworkInterfaceInput( void ) #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if( xResult > 0 ) { - pxStartDescriptor->pxInterface = pxMyInterface; - pxStartDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxStartDescriptor->pucEthernetBuffer ); xRxEvent.pvData = ( void * ) pxStartDescriptor; if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 100U ) != pdPASS ) { From 8f14d4dc41bf908acbf5e0a24843a517b9fe5d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 25 Sep 2023 10:13:42 +0200 Subject: [PATCH 08/68] Ignore packets whose buffers were dropped --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index a2f6dd582c..13189eadd2 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -542,6 +542,11 @@ static UBaseType_t prvNetworkInterfaceInput( void ) while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) { /*configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE );*/ + if( pxCurDescriptor == NULL ) + { + /* Buffer was dropped, ignore packet */ + continue; + } xResult++; pxCurDescriptor->pxInterface = pxMyInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer );; From bb367fda3dbd1376473b0ee2bf795be0844cab8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 25 Sep 2023 10:58:49 +0200 Subject: [PATCH 09/68] Fix formatting --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 13189eadd2..fcce64e044 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -547,6 +547,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) /* Buffer was dropped, ignore packet */ continue; } + xResult++; pxCurDescriptor->pxInterface = pxMyInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer );; From a747194e21c46665b9f73241d555b7a0199939f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Thu, 21 Sep 2023 14:08:02 +0200 Subject: [PATCH 10/68] Support network down event --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index a2f6dd582c..feaa05f98d 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -787,6 +787,10 @@ static void prvEthernetUpdateConfig( void ) /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ xHalResult = HAL_ETH_Stop_IT( &xEthHandle ); configASSERT( xHalResult == HAL_OK ); + + #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) + FreeRTOS_NetworkDown( pxMyInterface ); + #endif } } From 08604cf839180afd79d32c100ee6f71515ee9ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Fri, 22 Sep 2023 13:47:37 +0200 Subject: [PATCH 11/68] Don't return pdPASS on interface initialize when link is down --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index feaa05f98d..59512d3e76 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -396,7 +396,10 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte case eMACInitComplete: configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); - xInitResult = pdPASS; + if( xSTM32_GetPhyLinkStatus( pxInterface ) == pdPASS ) + { + xInitResult = pdPASS; + } } return xInitResult; From 57d78d95ae6b28908d60f8b7e2ee94d0374c3fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 25 Sep 2023 11:17:57 +0200 Subject: [PATCH 12/68] Fix formatting --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 59512d3e76..5730f5dfbc 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -396,6 +396,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte case eMACInitComplete: configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); + if( xSTM32_GetPhyLinkStatus( pxInterface ) == pdPASS ) { xInitResult = pdPASS; From 9cc1cfe551165c027791809c20356b7fa2f3bba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 25 Sep 2023 11:49:56 +0200 Subject: [PATCH 13/68] Include toplevel HAL headers --- .../portable/NetworkInterface/STM32/NetworkInterface.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index a2f6dd582c..8f3f896c0a 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -50,14 +50,13 @@ /* ST includes. */ #if defined( STM32F4 ) - #include "stm32f4xx_hal_eth.h" + #include "stm32f4xx_hal.h" #elif defined( STM32F7 ) - #include "stm32f7xx_hal_eth.h" + #include "stm32f7xx_hal.h" #elif defined( STM32H7 ) - #include "stm32h7xx_hal_eth.h" + #include "stm32h7xx_hal.h" #elif defined( STM32H5 ) - /* Untested */ - #include "stm32h5xx_hal_eth.h" + #include "stm32h5xx_hal.h" #else #error Unknown STM32 Family for NetworkInterface #endif From 41d699ce235babca20fd095f22206c4bc4aa84d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Mon, 25 Sep 2023 14:08:57 +0200 Subject: [PATCH 14/68] Clean redundant comment --- .../portable/NetworkInterface/STM32/NetworkInterface.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 5730f5dfbc..20f0d329b3 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -695,16 +695,6 @@ static void prvEMACHandlerTask( void * pvParameters ) if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { prvEthernetUpdateConfig(); - - /* - #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) - { - if( xGetPhyLinkStatus() == pdFALSE ) - { - FreeRTOS_NetworkDown(); - } - } - */ } } } From 80040688074da7c6624a983580eaadbb3fe26741 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 8 Nov 2023 18:39:51 -0500 Subject: [PATCH 15/68] Work on error handling --- .../NetworkInterface/STM32/NetworkInterface.c | 464 ++++++++++-------- 1 file changed, 258 insertions(+), 206 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index bab9dea736..2918f39416 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1,35 +1,3 @@ -/* - * Some constants, hardware definitions and comments taken from ST's HAL driver - * library, COPYRIGHT(c) 2015 STMicroelectronics. - */ - -/* - * FreeRTOS+TCP - * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * SPDX-License-Identifier: MIT - * - * 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 #include @@ -63,7 +31,7 @@ /*-----------------------------------------------------------*/ -/* TODO: This should be made moved from FreeRTOS_IP.c to FreeRTOS_IP_Private.h +/* TODO: This should be moved from FreeRTOS_IP.c to FreeRTOS_IP_Private.h * so that all the network interfaces don't have to keep defining it. */ #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer @@ -73,34 +41,40 @@ /*-----------------------------------------------------------*/ -#define EMAC_DATA_BUFFER_SIZE ( ipconfigNETWORK_MTU + ipSIZE_OF_ETH_HEADER ) -#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + 31U ) & ~0x1FuL ) - -#define EMAC_IF_RX_EVENT 1UL -#define EMAC_IF_TX_EVENT 2UL -#define EMAC_IF_TX_ERR_EVENT 4UL -#define EMAC_IF_RX_ERR_EVENT 8UL -#define EMAC_IF_DMA_ERR_EVENT 16UL -#define EMAC_IF_ETH_ERR_EVENT 32UL -#define EMAC_IF_MAC_ERR_EVENT 64UL -#define EMAC_IF_ALL_EVENT ( EMAC_IF_RX_EVENT | EMAC_IF_TX_EVENT | EMAC_IF_TX_ERR_EVENT | EMAC_IF_RX_ERR_EVENT | EMAC_IF_DMA_ERR_EVENT | EMAC_IF_ETH_ERR_EVENT | EMAC_IF_MAC_ERR_EVENT ) +#define EMAC_TX_DESCRIPTORS_SECTION ".TxDescripSection" +#define EMAC_RX_DESCRIPTORS_SECTION ".RxDescripSection" +#define EMAC_BUFFERS_SECTION ".EthBuffersSection" + +#define EMAC_DATA_ALIGNMENT_MASK ( portBYTE_ALIGNMENT - 1U ) +#define EMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~EMAC_DATA_ALIGNMENT_MASK ) +#define EMAC_TOTAL_ALIGNMENT_MASK ( __SCB_DCACHE_LINE_SIZE - 1U ) +#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + __SCB_DCACHE_LINE_SIZE ) & ~EMAC_TOTAL_ALIGNMENT_MASK ) + +typedef enum { + eMacEventRx = 1 << 0, + eMacEventTx = 1 << 1, + eMacEventErrRx = 1 << 2, + eMacEventErrTx = 1 << 3, + eMacEventErrDma = 1 << 4, + eMacEventErrEth = 1 << 5, + eMacEventErrMac = 1 << 6, + eMacEventAll = (1 << 7) - 1, +} eMAC_IF_EVENT; typedef enum { - eMACEthInit, - eMACPhyInit, - eMACPhyStart, - eMACTaskStart, - eMACEthStart, - eMACInitComplete + eMacEthInit, + eMacPhyInit, + eMacPhyStart, + eMacTaskStart, + eMacEthStart, + eMacInitComplete } eMAC_INIT_STATUS_TYPE; /*-----------------------------------------------------------*/ static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ); -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); - static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); @@ -109,7 +83,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ); static void prvEMACHandlerTask( void * pvParameters ) __attribute__( ( __noreturn__ ) ); -static BaseType_t prvAcceptPacket( NetworkBufferDescriptor_t * pxDescriptor ); +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ); static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); @@ -119,12 +93,7 @@ static void prvEthernetUpdateConfig( void ); /* static void prvMACAddressConfig( ETH_HandleTypeDef * heth, uint32_t ulIndex, uint8_t * Addr ); */ -#if ( ipconfigIPv4_BACKWARD_COMPATIBLE != 0 ) - NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) - { - return pxSTM32_FillInterfaceDescriptor( xEMACIndex, pxInterface ); - } -#endif +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); /*-----------------------------------------------------------*/ @@ -132,9 +101,9 @@ static ETH_HandleTypeDef xEthHandle; static ETH_MACConfigTypeDef xMACConfig; -static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( ".RxDescripSection" ), aligned( 4 ) ) ); +static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( EMAC_RX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); -static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( ".TxDescripSection" ), aligned( 4 ) ) ); +static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( EMAC_TX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); static NetworkInterface_t * pxMyInterface = NULL; @@ -156,9 +125,11 @@ static const PhyProperties_t xPHYProperties = { void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __attribute__( ( section( ".EthBuffersSection" ), aligned( 32 ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __attribute__( ( section( EMAC_BUFFERS_SECTION ), aligned( __SCB_DCACHE_LINE_SIZE ) ) ); - for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + configASSERT( xBufferAllocFixedSize == pdTRUE ); + + for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++ul ) { pxNetworkBuffers[ ul ].pucEthernetBuffer = &( ucNetworkPackets[ ul ][ ipBUFFER_PADDING ] ); *( ( uint32_t * ) &( ucNetworkPackets[ ul ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ ul ] ) ); @@ -167,51 +138,54 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB /*-----------------------------------------------------------*/ -static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) -{ - ( void ) pxInterface; - - BaseType_t xReturn = pdFAIL; - - if( xPhyObject.ulLinkStatusMask != 0U ) - { - xReturn = pdPASS; - } - - return xReturn; -} - -/*-----------------------------------------------------------*/ - NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { static char pcName[ 17 ]; - snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); + ( void ) snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); - memset( pxInterface, '\0', sizeof( *pxInterface ) ); + ( void ) memset( pxInterface, '\0', sizeof( *pxInterface ) ); pxInterface->pcName = pcName; pxInterface->pvArgument = ( void * ) xEMACIndex; pxInterface->pfInitialise = xSTM32_NetworkInterfaceInitialise; pxInterface->pfOutput = xSTM32_NetworkInterfaceOutput; pxInterface->pfGetPhyLinkStatus = xSTM32_GetPhyLinkStatus; - FreeRTOS_AddNetworkInterface( pxInterface ); + ( void ) FreeRTOS_AddNetworkInterface( pxInterface ); + + pxMyInterface = pxInterface; return pxInterface; } /*-----------------------------------------------------------*/ +static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) +{ + ( void ) pxInterface; + + BaseType_t xReturn = pdFAIL; + + if( xPhyObject.ulLinkStatusMask != 0U ) + { + xReturn = pdPASS; + } + + return xReturn; +} + +/*-----------------------------------------------------------*/ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xInitResult = pdFAIL; BaseType_t xResult; HAL_StatusTypeDef xHalResult; - NetworkEndPoint_t * pxEndPoint; /* BaseType_t xMACEntry = ETH_MAC_ADDRESS1; */ /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACEthInit; + static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; switch( xMacInitStatus ) { @@ -219,21 +193,23 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte configASSERT( pdFALSE ); break; - case eMACEthInit: - pxMyInterface = pxInterface; + case eMacEthInit: + xEthHandle.Instance = ETH; - pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); - configASSERT( pxEndPoint != NULL ); + const NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + if( pxEndPoint == NULL ) + { + break; + } - xEthHandle.Instance = ETH; - xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; /* FreeRTOS_GetMACAddress(); */ + xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; xEthHandle.Init.TxDesc = DMATxDscrTab; xEthHandle.Init.RxDesc = DMARxDscrTab; xEthHandle.Init.RxBuffLen = EMAC_DATA_BUFFER_SIZE; - memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); - memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); + ( void ) memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); + ( void ) memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); #if defined( STM32F7 ) || defined( STM32F4 ) /* This function doesn't get called in Fxx driver */ @@ -243,15 +219,17 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte xHalResult = HAL_ETH_Init( &xEthHandle ); if( xHalResult != HAL_OK ) { + /* &xEthHandle != NULL + xEthHandle.ErrorCode == HAL_ETH_ERROR_TIMEOUT */ break; } configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - xMacInitStatus = eMACPhyInit; - /* Fallthrough */ + xMacInitStatus = eMacPhyInit; + /* fallthrough */ - case eMACPhyInit: + case eMacPhyInit: vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); xResult = xPhyDiscover( &xPhyObject ); @@ -260,22 +238,22 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte break; } + xMacInitStatus = eMacPhyStart; + /* fallthrough */ + + case eMacPhyStart: xResult = xPhyConfigure( &xPhyObject, &xPHYProperties ); if( xResult != 0 ) { break; } - xMacInitStatus = eMACPhyStart; - /* Fallthrough */ - - case eMACPhyStart: if ( xSTM32_GetPhyLinkStatus( pxInterface ) == pdFAIL ) { xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ configASSERT( xResult == 0 ); - if ( xSTM32_GetPhyLinkStatus( pxMyInterface ) == pdFAIL ) + if ( xSTM32_GetPhyLinkStatus( pxInterface ) == pdFAIL ) { break; } @@ -297,10 +275,10 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte break; } - xMacInitStatus = eMACTaskStart; - /* Fallthrough */ + xMacInitStatus = eMacTaskStart; + /* fallthrough */ - case eMACTaskStart: + case eMacTaskStart: if( xTxMutex == NULL ) { #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) @@ -349,7 +327,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte xEMACTaskHandle = xTaskCreateStatic( prvEMACHandlerTask, "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), + ( 2 * configMINIMAL_STACK_SIZE ), /* ipconfigEMAC_TASK_STACK_SIZE */ NULL, ( configMAX_PRIORITIES - 1 ), uxEMACTaskStack, @@ -360,7 +338,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte xResult = xTaskCreate( prvEMACHandlerTask, "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), + ( 2 * configMINIMAL_STACK_SIZE ), /* ipconfigEMAC_TASK_STACK_SIZE */ NULL, ( configMAX_PRIORITIES - 1 ), &xEMACTaskHandle @@ -374,10 +352,10 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte } } - xMacInitStatus = eMACEthStart; - /* Fallthrough */ + xMacInitStatus = eMacEthStart; + /* fallthrough */ - case eMACEthStart: + case eMacEthStart: if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) { xHalResult = HAL_ETH_Start_IT( &xEthHandle ); @@ -388,14 +366,13 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte } } configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); - configASSERT( xEthHandle.RxDescList.ItMode == 1U); + configASSERT( xEthHandle.RxDescList.ItMode == 1U ); - xMacInitStatus = eMACInitComplete; - /* Fallthrough */ + xMacInitStatus = eMacInitComplete; + /* fallthrough */ - case eMACInitComplete: + case eMacInitComplete: configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); - if( xSTM32_GetPhyLinkStatus( pxInterface ) == pdPASS ) { xInitResult = pdPASS; @@ -404,6 +381,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte return xInitResult; } +#pragma GCC diagnostic pop /*-----------------------------------------------------------*/ @@ -411,8 +389,8 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac { BaseType_t xResult = pdFAIL; configASSERT( pxDescriptor != NULL ); - /* Zero-Copy Only */ - configASSERT( xReleaseAfterSend != pdFALSE ); + configASSERT( xReleaseAfterSend != pdFALSE ); /* Zero-Copy Only */ + iptraceNETWORK_INTERFACE_OUTPUT( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ); if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= EMAC_DATA_BUFFER_SIZE ) ) { @@ -480,7 +458,7 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac } else { - xSemaphoreGive( xTxDescSem ); + ( void ) xSemaphoreGive( xTxDescSem ); configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) { @@ -489,7 +467,8 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac if( xEthHandle.ErrorCode & HAL_ETH_ERROR_BUSY ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); - HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); } } } @@ -522,7 +501,7 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac /*if( xResult == pdFAIL ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Failed\n" ) ); - xTaskNotify( xEMACTaskHandle, EMAC_IF_TX_ERR_EVENT, eSetBits ); + xTaskNotify( xEMACTaskHandle, eMacEventErrTx, eSetBits ); }*/ return xResult; @@ -538,22 +517,19 @@ static UBaseType_t prvNetworkInterfaceInput( void ) NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; - IPStackEvent_t xRxEvent = { - .eEventType = eNetworkRxEvent, - .pvData = NULL - }; + while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) { - /*configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE );*/ + /* configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE ); */ if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ continue; } - - xResult++; + iptraceNETWORK_INTERFACE_INPUT( pxCurDescriptor->xDataLength, pxCurDescriptor->pucEthernetBuffer ); + ++xResult; pxCurDescriptor->pxInterface = pxMyInterface; - pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxMyInterface, pxCurDescriptor->pucEthernetBuffer );; + pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if ( pxStartDescriptor == NULL ) { @@ -575,11 +551,13 @@ static UBaseType_t prvNetworkInterfaceInput( void ) #endif } - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if( xResult > 0 ) { - xRxEvent.pvData = ( void * ) pxStartDescriptor; + const IPStackEvent_t xRxEvent = { + .eEventType = eNetworkRxEvent, + .pvData = ( void * ) pxStartDescriptor, + }; if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 100U ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); @@ -596,14 +574,15 @@ static UBaseType_t prvNetworkInterfaceInput( void ) if( xResult == 0 ) { - xTaskNotify( xEMACTaskHandle, EMAC_IF_RX_ERR_EVENT, eSetBits ); + ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); } configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) { - xTaskNotify( xEMACTaskHandle, EMAC_IF_ETH_ERR_EVENT, eSetBits ); + ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); } + return ( BaseType_t ) ( xResult > 0 ); } @@ -618,27 +597,25 @@ static void prvEMACHandlerTask( void * pvParameters ) BaseType_t xResult = 0U; uint32_t ulISREvents = 0U; - if ( xTaskNotifyWait( 0U, EMAC_IF_ALL_EVENT, &ulISREvents, pdMS_TO_TICKS( 100UL ) ) == pdTRUE ) + if ( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( 100UL ) ) == pdTRUE ) { HAL_StatusTypeDef xHalResult; - if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventRx ) != 0 ) { - iptraceNETWORK_INTERFACE_RECEIVE(); xResult = ( prvNetworkInterfaceInput() > 0 ); } - if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventTx ) != 0 ) { - iptraceNETWORK_INTERFACE_TRANSMIT(); if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) { xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); configASSERT( xHalResult == HAL_OK ); - xSemaphoreGive( xTxMutex ); + ( void ) xSemaphoreGive( xTxMutex ); } } - if( ( ulISREvents & EMAC_IF_TX_ERR_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventErrTx ) != 0 ) { if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) { @@ -646,12 +623,12 @@ static void prvEMACHandlerTask( void * pvParameters ) configASSERT( xHalResult == HAL_OK ); while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > xEthHandle.TxDescList.BuffersInUse ) { - xSemaphoreGive( xTxDescSem ); + ( void ) xSemaphoreGive( xTxDescSem ); } } } - if( ( ulISREvents & EMAC_IF_RX_ERR_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventErrRx ) != 0 ) { /*do { xResult = ( prvNetworkInterfaceInput() > 0 ); @@ -659,18 +636,18 @@ static void prvEMACHandlerTask( void * pvParameters ) xResult = pdTRUE;*/ } - if( ( ulISREvents & EMAC_IF_ETH_ERR_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventErrEth ) != 0 ) { /* xEthHandle.gState */ /* xEthHandle.ErrorCode */ } - if( ( ulISREvents & EMAC_IF_MAC_ERR_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventErrMac ) != 0 ) { /* xEthHandle.MACErrorCode */ } - if( ( ulISREvents & EMAC_IF_DMA_ERR_EVENT ) != 0 ) + if( ( ulISREvents & eMacEventErrDma ) != 0 ) { /* TODO: Does this recover from fatal bus error? */ if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 5000U ) ) != pdFALSE ) @@ -695,30 +672,37 @@ static void prvEMACHandlerTask( void * pvParameters ) xSemaphoreGive( xTxMutex ); } } + + (void) xHalResult; } if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { - prvEthernetUpdateConfig(); + if( xEthHandle.gState != HAL_ETH_STATE_BUSY ) + { + prvEthernetUpdateConfig(); + } } } } /*-----------------------------------------------------------*/ -static BaseType_t prvAcceptPacket( NetworkBufferDescriptor_t * pxDescriptor ) +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ) { BaseType_t xResult = pdFALSE; uint32_t pErrorCode = 0; - HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); + const HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); configASSERT( xHalResult == HAL_OK ); + (void) xHalResult; + /* Fxx - ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT | ETH_DMARXDESC_LC | ETH_DMARXDESC_CE | ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE */ /* Hxx - ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT | ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE */ if ( pErrorCode == 0 ) { - eFrameProcessingResult_t xFrameProcessingResult = ipCONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); + const eFrameProcessingResult_t xFrameProcessingResult = ipCONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); if( xFrameProcessingResult == eProcessBuffer ) { xResult = pdTRUE; @@ -791,6 +775,9 @@ static void prvEthernetUpdateConfig( void ) FreeRTOS_NetworkDown( pxMyInterface ); #endif } + + (void) xHalResult; + (void) xResult; } /*-----------------------------------------------------------*/ @@ -819,86 +806,109 @@ void ETH_IRQHandler( void ) /*-----------------------------------------------------------*/ -void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) -{ - static size_t uxMostRXDescsUsed = 0U; - - const size_t uxRxUsed = heth->RxDescList.RxDescCnt; - - if( uxMostRXDescsUsed < uxRxUsed ) - { - uxMostRXDescsUsed = uxRxUsed; - } - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -} - -/*-----------------------------------------------------------*/ - -void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) -{ - static size_t uxMostTXDescsUsed = 0U; - - const size_t uxTxUsed = heth->TxDescList.BuffersInUse; - - if( uxMostTXDescsUsed < uxTxUsed ) - { - uxMostTXDescsUsed = uxTxUsed; - } - - BaseType_t xHigherPriorityTaskWoken = pdFALSE; -// vTaskNotifyGiveIndexedFromISR( xEMACTaskHandle, TX_INDEX, &xHigherPriorityTaskWoken ); - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -} - -/*-----------------------------------------------------------*/ - void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { - // volatile uint32_t errs = heth->Instance->DMASR; BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if( HAL_ETH_GetError( heth ) & HAL_ETH_ERROR_DMA ) + if( heth->ErrorCode & HAL_ETH_ERROR_DMA ) { - if( HAL_ETH_GetDMAError( heth ) ) + if( heth->DMAErrorCode ) { + /*volatile uint32_t errs = heth->Instance->DMASR; + #if defined ( STM32H5 ) || defined ( STM32H7 ) + ETH_DMARXNDESCWBF_ERRORS_MASK + #elif defined ( STM32F4 ) || defined ( STM32F7 ) + HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode) + ETH_DMARXDESC_ERRORS_MASK + #endif*/ + /*ETH_DMA_RX_NO_ERROR_FLAG + ETH_DMA_RX_DESC_READ_ERROR_FLAG + ETH_DMA_RX_DESC_WRITE_ERROR_FLAG + ETH_DMA_RX_BUFFER_READ_ERROR_FLAG + ETH_DMA_RX_BUFFER_WRITE_ERROR_FLAG + ETH_DMA_TX_NO_ERROR_FLAG + ETH_DMA_TX_DESC_READ_ERROR_FLAG + ETH_DMA_TX_DESC_WRITE_ERROR_FLAG + ETH_DMA_TX_BUFFER_READ_ERROR_FLAG + ETH_DMA_TX_BUFFER_WRITE_ERROR_FLAG + ETH_DMA_CONTEXT_DESC_ERROR_FLAG + ETH_DMA_FATAL_BUS_ERROR_FLAG + ETH_DMA_EARLY_TX_IT_FLAG + ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG + ETH_DMA_RX_PROCESS_STOPPED_FLAG + ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG + ETH_DMA_TX_PROCESS_STOPPED_FLAG + ETH_DMA_OVERFLOW_RXFIFOCOUNTER + ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER*/ + if( heth->gState == HAL_ETH_STATE_ERROR ) { /* fatal bus error occurred */ /* Fxx - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ /* Hxx - ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS */ - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_DMA_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrDma, eSetBits, &xHigherPriorityTaskWoken ); } else { /* Fxx - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ /* Hxx - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ #if defined( STM32F4 ) || defined ( STM32F7 ) - if((HAL_ETH_GetDMAError(heth) & ETH_DMASR_TBUS) == ETH_DMASR_TBUS) + if( ( heth->DMAErrorCode & ETH_DMASR_TBUS ) == ETH_DMASR_TBUS) { - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); } - if((HAL_ETH_GetDMAError(heth) & ETH_DMASR_RBUS) == ETH_DMASR_RBUS) + if( ( heth->DMAErrorCode & ETH_DMASR_RBUS ) == ETH_DMASR_RBUS) { - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); + /*ETH_DRIBBLE_BIT_ERROR + ETH_RECEIVE_ERROR + ETH_RECEIVE_OVERFLOW + ETH_WATCHDOG_TIMEOUT + ETH_GIANT_PACKET + ETH_CRC_ERROR + ETH_VLAN_FILTER_PASS + ETH_DEST_ADDRESS_FAIL + ETH_SOURCE_ADDRESS_FAIL*/ } #endif } } } - #if defined( STM32H7 ) || defined ( STM32H5 ) - if( HAL_ETH_GetError( heth ) & HAL_ETH_ERROR_MAC ) + if( heth->ErrorCode & HAL_ETH_ERROR_MAC ) + { + if( heth->MACErrorCode ) { - if( HAL_ETH_GetMACError( heth ) ) - { - xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_MAC_ERR_EVENT, eSetBits, &xHigherPriorityTaskWoken ); - } + /*ETH_RECEIVE_WATCHDOG_TIMEOUT + ETH_EXECESSIVE_COLLISIONS + ETH_LATE_COLLISIONS + ETH_EXECESSIVE_DEFERRAL + ETH_LOSS_OF_CARRIER + ETH_NO_CARRIER + ETH_TRANSMIT_JABBR_TIMEOUT*/ + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); } - #endif + } + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); +} + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostRXDescsUsed = 0U; + + const size_t uxRxUsed = heth->RxDescList.RxDescCnt; + + if( uxMostRXDescsUsed < uxRxUsed ) + { + uxMostRXDescsUsed = uxRxUsed; + } + + iptraceNETWORK_INTERFACE_RECEIVE(); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventRx, eSetBits, &xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } @@ -906,7 +916,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) void HAL_ETH_RxAllocateCallback( uint8_t **buff ) { - NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( 200U ) ); + const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( 200U ) ); if( pxBufferDescriptor != NULL ) { *buff = pxBufferDescriptor->pucEthernetBuffer; @@ -921,9 +931,9 @@ void HAL_ETH_RxAllocateCallback( uint8_t **buff ) void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) { - NetworkBufferDescriptor_t ** pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; - NetworkBufferDescriptor_t ** pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; - NetworkBufferDescriptor_t * pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); + NetworkBufferDescriptor_t ** const pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; + NetworkBufferDescriptor_t ** const pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; + NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); if ( Length <= EMAC_DATA_BUFFER_SIZE && prvAcceptPacket( pxCurDescriptor ) == pdTRUE ) { pxCurDescriptor->xDataLength = Length; @@ -950,9 +960,9 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t NetworkBufferDescriptor_t * pxDescriptorToClear = pxCurDescriptor; do { #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; + NetworkBufferDescriptor_t * const pxNext = pxDescriptorToClear->pxNextBuffer; #else - NetworkBufferDescriptor_t * pxNext = NULL; + NetworkBufferDescriptor_t * const pxNext = NULL; #endif vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); pxDescriptorToClear = pxNext; @@ -962,11 +972,53 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t /*-----------------------------------------------------------*/ +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) +{ + static size_t uxMostTXDescsUsed = 0U; + + const size_t uxTxUsed = heth->TxDescList.BuffersInUse; + + if( uxMostTXDescsUsed < uxTxUsed ) + { + uxMostTXDescsUsed = uxTxUsed; + } + + iptraceNETWORK_INTERFACE_TRANSMIT(); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + /* vTaskNotifyGiveIndexedFromISR( xEMACTaskHandle, TX_INDEX, &xHigherPriorityTaskWoken ); */ + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + + /* if( xBufferAllocFixedSize == pdTRUE ) + { + if( xSemaphoreTakeFromISR( xTxMutex, &xHigherPriorityTaskWoken ) != pdFALSE ) + { + const HAL_StatusTypeDef xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + configASSERT( xHalResult == HAL_OK ); + ( void ) xSemaphoreGiveFromISR( xTxMutex, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + } */ +} + +/*-----------------------------------------------------------*/ + void HAL_ETH_TxFreeCallback( uint32_t *buff ) { - NetworkBufferDescriptor_t * pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; + NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - xSemaphoreGive( xTxDescSem ); + ( void ) xSemaphoreGive( xTxDescSem ); + + /* + if( xBufferAllocFixedSize == pdTRUE ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xReleaseNetworkBufferFromISR( pxNetworkBuffer ); + ( void ) xSemaphoreGiveFromISR( xTxDescSem, &xHigherPriorityTaskWoken ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } + */ } /*-----------------------------------------------------------*/ From 07c53216e6169110382ef10fb4a05819281e2128 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 3 Dec 2023 09:00:03 -0500 Subject: [PATCH 16/68] re-add doc --- .../NetworkInterface/STM32/NetworkInterface.c | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 2918f39416..0b259f97db 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1,3 +1,35 @@ +/* + * Some constants, hardware definitions and comments taken from ST's HAL driver + * library, COPYRIGHT(c) 2015 STMicroelectronics. + */ + +/* + * FreeRTOS+TCP + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * 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 #include @@ -176,8 +208,6 @@ static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) /*-----------------------------------------------------------*/ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xInitResult = pdFAIL; @@ -381,7 +411,6 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte return xInitResult; } -#pragma GCC diagnostic pop /*-----------------------------------------------------------*/ From 03cf5c24bc042a5ee16b52087f664fe49cdb51f1 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 3 Dec 2023 14:34:26 -0500 Subject: [PATCH 17/68] clean network interface --- .../NetworkInterface/STM32/NetworkInterface.c | 44 +------------------ 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 0b259f97db..9457b6c805 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -842,33 +842,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { if( heth->DMAErrorCode ) { - /*volatile uint32_t errs = heth->Instance->DMASR; - #if defined ( STM32H5 ) || defined ( STM32H7 ) - ETH_DMARXNDESCWBF_ERRORS_MASK - #elif defined ( STM32F4 ) || defined ( STM32F7 ) - HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode) - ETH_DMARXDESC_ERRORS_MASK - #endif*/ - /*ETH_DMA_RX_NO_ERROR_FLAG - ETH_DMA_RX_DESC_READ_ERROR_FLAG - ETH_DMA_RX_DESC_WRITE_ERROR_FLAG - ETH_DMA_RX_BUFFER_READ_ERROR_FLAG - ETH_DMA_RX_BUFFER_WRITE_ERROR_FLAG - ETH_DMA_TX_NO_ERROR_FLAG - ETH_DMA_TX_DESC_READ_ERROR_FLAG - ETH_DMA_TX_DESC_WRITE_ERROR_FLAG - ETH_DMA_TX_BUFFER_READ_ERROR_FLAG - ETH_DMA_TX_BUFFER_WRITE_ERROR_FLAG - ETH_DMA_CONTEXT_DESC_ERROR_FLAG - ETH_DMA_FATAL_BUS_ERROR_FLAG - ETH_DMA_EARLY_TX_IT_FLAG - ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG - ETH_DMA_RX_PROCESS_STOPPED_FLAG - ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG - ETH_DMA_TX_PROCESS_STOPPED_FLAG - ETH_DMA_OVERFLOW_RXFIFOCOUNTER - ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER*/ - if( heth->gState == HAL_ETH_STATE_ERROR ) { /* fatal bus error occurred */ @@ -889,15 +862,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) if( ( heth->DMAErrorCode & ETH_DMASR_RBUS ) == ETH_DMASR_RBUS) { ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); - /*ETH_DRIBBLE_BIT_ERROR - ETH_RECEIVE_ERROR - ETH_RECEIVE_OVERFLOW - ETH_WATCHDOG_TIMEOUT - ETH_GIANT_PACKET - ETH_CRC_ERROR - ETH_VLAN_FILTER_PASS - ETH_DEST_ADDRESS_FAIL - ETH_SOURCE_ADDRESS_FAIL*/ } #endif } @@ -908,16 +872,10 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { if( heth->MACErrorCode ) { - /*ETH_RECEIVE_WATCHDOG_TIMEOUT - ETH_EXECESSIVE_COLLISIONS - ETH_LATE_COLLISIONS - ETH_EXECESSIVE_DEFERRAL - ETH_LOSS_OF_CARRIER - ETH_NO_CARRIER - ETH_TRANSMIT_JABBR_TIMEOUT*/ ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); } } + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } From 1f3e33b1d3f59cf29d94c841daa3c8d85b77eda2 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 3 Dec 2023 16:32:36 -0500 Subject: [PATCH 18/68] add more mac features --- .../NetworkInterface/STM32/NetworkInterface.c | 99 ++++++++++++++++--- 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 9457b6c805..3cc37cb034 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -123,7 +123,7 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static void prvEthernetUpdateConfig( void ); -/* static void prvMACAddressConfig( ETH_HandleTypeDef * heth, uint32_t ulIndex, uint8_t * Addr ); */ +static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * Addr ); NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); @@ -131,8 +131,6 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net static ETH_HandleTypeDef xEthHandle; -static ETH_MACConfigTypeDef xMACConfig; - static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( EMAC_RX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( EMAC_TX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); @@ -213,7 +211,6 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte BaseType_t xInitResult = pdFAIL; BaseType_t xResult; HAL_StatusTypeDef xHalResult; - /* BaseType_t xMACEntry = ETH_MAC_ADDRESS1; */ /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; @@ -226,7 +223,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte case eMacEthInit: xEthHandle.Instance = ETH; - const NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); if( pxEndPoint == NULL ) { break; @@ -256,6 +253,65 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); + #if 0 + ETH_MACFilterConfigTypeDef xFilterConfig; + xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); + + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.HashMulticast = ENABLE; + xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); + + const uint32_t ulHashTable = 0x00; + xHalResult = HAL_ETH_SetHashTable( &xEthHandle, &ulHashTable ); + configASSERT( xHalResult == HAL_OK ); + #endif + + #if ( ipconfigUSE_MDNS != 0 ) + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MACAddress.ucBytes ); + #if ( ipconfigUSE_IPv6 != 0 ) + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MACAddressIPv6.ucBytes ); + #endif + #endif + + #if ( ipconfigUSE_LLMNR != 0 ) + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MACAddress.ucBytes ); + #if ( ipconfigUSE_IPv6 != 0 ) + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MacAddressIPv6.ucBytes ); + #endif + #endif + + for(; pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + #if ( ipconfigUSE_IPv6 != 0 ) + if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) + { + const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { + 0x33, + 0x33, + 0xff, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + }; + prvMACAddressConfig( &xEthHandle, ucMACAddress ); + } + #else + { + if( xEthHandle.Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) + { + prvMACAddressConfig( &xEthHandle, pxEndPoint->xMACAddress.ucBytes ); + } + } + #endif + } + + #if ( ipconfigUSE_IPv6 != 0 ) + const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33, 0x33, 0, 0, 0, 0x01 }; + prvMACAddressConfig( &xEthHandle, ucMACAddress ); + #endif + xMacInitStatus = eMacPhyInit; /* fallthrough */ @@ -289,6 +345,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte } } + ETH_MACConfigTypeDef xMACConfig; xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); configASSERT( xHalResult == HAL_OK ); if( xHalResult != HAL_OK ) @@ -731,6 +788,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes if ( pErrorCode == 0 ) { + // ipconfigETHERNET_DRIVER_FILTERS_PACKETS const eFrameProcessingResult_t xFrameProcessingResult = ipCONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); if( xFrameProcessingResult == eProcessBuffer ) { @@ -782,6 +840,7 @@ static void prvEthernetUpdateConfig( void ) xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); configASSERT( xResult == 0 ); + ETH_MACConfigTypeDef xMACConfig; xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); configASSERT( xHalResult == HAL_OK ); @@ -811,20 +870,34 @@ static void prvEthernetUpdateConfig( void ) /*-----------------------------------------------------------*/ -/*static void prvMACAddressConfig( ETH_HandleTypeDef * heth, uint32_t ulIndex, uint8_t * addr ) +static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * addr ) { - uint32_t ulTempReg; + static BaseType_t xMACEntry = ETH_MAC_ADDRESS1; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - ( void ) heth; + switch(xMACEntry) + { + case ETH_MAC_ADDRESS1: + HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS1, addr ); + xMACEntry = ETH_MAC_ADDRESS2; + break; - ulTempReg = 0x80000000ul | ( ( uint32_t ) addr[ 5 ] << 8 ) | ( uint32_t ) addr[ 4 ]; + case ETH_MAC_ADDRESS2: + HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS2, addr ); + xMACEntry = ETH_MAC_ADDRESS3; + break; - ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg; + case ETH_MAC_ADDRESS3: + HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS3, addr ); + xMACEntry = ETH_MAC_ADDRESS0; + break; - ulTempReg = ( ( uint32_t ) addr[ 3 ] << 24 ) | ( ( uint32_t ) addr[ 2 ] << 16 ) | ( ( uint32_t ) addr[ 1 ] << 8 ) | addr[ 0 ]; + case ETH_MAC_ADDRESS0: + /* fallthrough */ - ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg; -}*/ + default: + break; + } +} /*-----------------------------------------------------------*/ From 6a50bbb8b8e7cb2c6c1a469740bda6bbaac8d7b8 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 4 Dec 2023 16:29:04 -0500 Subject: [PATCH 19/68] attribute fixes --- .../NetworkInterface/STM32/NetworkInterface.c | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 3cc37cb034..34c815f631 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -63,8 +63,6 @@ /*-----------------------------------------------------------*/ -/* TODO: This should be moved from FreeRTOS_IP.c to FreeRTOS_IP_Private.h - * so that all the network interfaces don't have to keep defining it. */ #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #else @@ -77,10 +75,18 @@ #define EMAC_RX_DESCRIPTORS_SECTION ".RxDescripSection" #define EMAC_BUFFERS_SECTION ".EthBuffersSection" -#define EMAC_DATA_ALIGNMENT_MASK ( portBYTE_ALIGNMENT - 1U ) -#define EMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~EMAC_DATA_ALIGNMENT_MASK ) -#define EMAC_TOTAL_ALIGNMENT_MASK ( __SCB_DCACHE_LINE_SIZE - 1U ) -#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + __SCB_DCACHE_LINE_SIZE ) & ~EMAC_TOTAL_ALIGNMENT_MASK ) +/* TODO: Cache Handling + * This is only for F7 which uses M7, H5 uses M33, how does this work with dual core H7 M7/M4? + * Can probably align by portBYTE_ALIGNMENT if not cached */ +#ifdef __SCB_DCACHE_LINE_SIZE + #define EMAC_CACHE_LINE_SIZE __SCB_DCACHE_LINE_SIZE +#else + #define EMAC_CACHE_LINE_SIZE 32U +#endif + +#define EMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~portBYTE_ALIGNMENT_MASK ) +#define EMAC_TOTAL_ALIGNMENT_MASK ( EMAC_CACHE_LINE_SIZE - 1U ) +#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + EMAC_CACHE_LINE_SIZE ) & ~EMAC_TOTAL_ALIGNMENT_MASK ) typedef enum { eMacEventRx = 1 << 0, @@ -113,7 +119,7 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac static UBaseType_t prvNetworkInterfaceInput( void ); -static void prvEMACHandlerTask( void * pvParameters ) __attribute__( ( __noreturn__ ) ); +static void prvEMACHandlerTask( void * pvParameters ) __NO_RETURN; static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ); @@ -131,9 +137,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net static ETH_HandleTypeDef xEthHandle; -static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __attribute__( ( section( EMAC_RX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); +static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( EMAC_RX_DESCRIPTORS_SECTION ) ) ); -static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __attribute__( ( section( EMAC_TX_DESCRIPTORS_SECTION ), aligned( portBYTE_ALIGNMENT ) ) ); +static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( EMAC_TX_DESCRIPTORS_SECTION ) ) ); static NetworkInterface_t * pxMyInterface = NULL; @@ -155,7 +161,7 @@ static const PhyProperties_t xPHYProperties = { void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __attribute__( ( section( EMAC_BUFFERS_SECTION ), aligned( __SCB_DCACHE_LINE_SIZE ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( EMAC_CACHE_LINE_SIZE ) __attribute__( ( section( EMAC_BUFFERS_SECTION ) ) ); configASSERT( xBufferAllocFixedSize == pdTRUE ); @@ -269,14 +275,14 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte #endif #if ( ipconfigUSE_MDNS != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MACAddress.ucBytes ); + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MacAddress.ucBytes ); #if ( ipconfigUSE_IPv6 != 0 ) prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MACAddressIPv6.ucBytes ); #endif #endif #if ( ipconfigUSE_LLMNR != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MACAddress.ucBytes ); + prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MacAddress.ucBytes ); #if ( ipconfigUSE_IPv6 != 0 ) prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MacAddressIPv6.ucBytes ); #endif @@ -616,6 +622,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) ++xResult; pxCurDescriptor->pxInterface = pxMyInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); + /* TODO: check pxEndPoint exists? Check it earlier before getting buffer? */ #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if ( pxStartDescriptor == NULL ) { From 74b7548a54c4f76ecad42e44cf019d66ac427f24 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 11 Dec 2023 10:20:09 -0500 Subject: [PATCH 20/68] remove commented out code and implement fixed configuration --- .../NetworkInterface/STM32/NetworkInterface.c | 328 ++++++++++-------- 1 file changed, 180 insertions(+), 148 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 34c815f631..eb76aebf16 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1,6 +1,6 @@ /* * Some constants, hardware definitions and comments taken from ST's HAL driver - * library, COPYRIGHT(c) 2015 STMicroelectronics. + * library, COPYRIGHT(c) 2017 STMicroelectronics. */ /* @@ -57,37 +57,78 @@ #include "stm32h7xx_hal.h" #elif defined( STM32H5 ) #include "stm32h5xx_hal.h" +#elif defined( STM32F2 ) + #error This NetworkInterface is incompatible with STM32F2 - Use Legacy NetworkInterface #else #error Unknown STM32 Family for NetworkInterface #endif /*-----------------------------------------------------------*/ -#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer -#else - #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#if ( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) + #if ( ipconfigPORT_SUPPRESS_WARNING == 0 ) + #warning Consider enabling checksum offloading for NetworkInterface + #endif +#endif + +#if ( ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) ) + #if ( ipconfigPORT_SUPPRESS_WARNING == 0 ) + #warning Unsupported ipconfigNETWORK_MTU size + #endif #endif /*-----------------------------------------------------------*/ -#define EMAC_TX_DESCRIPTORS_SECTION ".TxDescripSection" -#define EMAC_RX_DESCRIPTORS_SECTION ".RxDescripSection" -#define EMAC_BUFFERS_SECTION ".EthBuffersSection" +#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + #define niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer +#else + #define niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#endif + +#define niEMAC_TX_DESC_SECTION ".TxDescripSection" +#define niEMAC_RX_DESC_SECTION ".RxDescripSection" +#define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -/* TODO: Cache Handling +/* + * TODO: Cache Handling * This is only for F7 which uses M7, H5 uses M33, how does this work with dual core H7 M7/M4? - * Can probably align by portBYTE_ALIGNMENT if not cached */ + * Can probably align by portBYTE_ALIGNMENT if not cached + */ #ifdef __SCB_DCACHE_LINE_SIZE - #define EMAC_CACHE_LINE_SIZE __SCB_DCACHE_LINE_SIZE + #define niEMAC_CACHE_LINE_SIZE __SCB_DCACHE_LINE_SIZE #else - #define EMAC_CACHE_LINE_SIZE 32U + #define niEMAC_CACHE_LINE_SIZE 32U +#endif + +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~portBYTE_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_ALIGNMENT_MASK ( niEMAC_CACHE_LINE_SIZE - 1U ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) + +#define niEMAC_MAX_BLOCK_TIME_MS 100U +#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U + +#define niEMAC_TASK_NAME "EMAC_STM32" +#define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) + +#define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" +#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" + +#define niEMAC_AUTO_NEGOTIATION 1 +#define niEMAC_AUTO_CROSS 1 + +#if ( niEMAC_AUTO_NEGOTIATION == 0 ) + #define niEMAC_CROSSED_LINK 1 + #define niEMAC_USE_100MB 1 + #define niEMAC_USE_FULL_DUPLEX 1 #endif -#define EMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~portBYTE_ALIGNMENT_MASK ) -#define EMAC_TOTAL_ALIGNMENT_MASK ( EMAC_CACHE_LINE_SIZE - 1U ) -#define EMAC_TOTAL_BUFFER_SIZE ( ( EMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + EMAC_CACHE_LINE_SIZE ) & ~EMAC_TOTAL_ALIGNMENT_MASK ) +#define niEMAC_USE_RMII 1 + +/*-----------------------------------------------------------*/ + +/* Interrupt events to process: reception, transmission and error handling. */ typedef enum { eMacEventRx = 1 << 0, eMacEventTx = 1 << 1, @@ -101,28 +142,30 @@ typedef enum { typedef enum { - eMacEthInit, - eMacPhyInit, - eMacPhyStart, - eMacTaskStart, - eMacEthStart, - eMacInitComplete + eMacEthInit, /* Must initialise ETH. */ + eMacPhyInit, /* Must initialise PHY. */ + eMacPhyStart, /* Must start PHY. */ + eMacTaskStart, /* Must start deferred interrupt handler task. */ + eMacEthStart, /* Must start ETH. */ + eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; /*-----------------------------------------------------------*/ -static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ); +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); -static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); +static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); -static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); +static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); static UBaseType_t prvNetworkInterfaceInput( void ); -static void prvEMACHandlerTask( void * pvParameters ) __NO_RETURN; +static portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ) __NO_RETURN; static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ); +static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); + static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); @@ -131,37 +174,54 @@ static void prvEthernetUpdateConfig( void ); static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * Addr ); -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); - /*-----------------------------------------------------------*/ static ETH_HandleTypeDef xEthHandle; -static ETH_DMADescTypeDef DMARxDscrTab[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( EMAC_RX_DESCRIPTORS_SECTION ) ) ); +static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); -static ETH_DMADescTypeDef DMATxDscrTab[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( EMAC_TX_DESCRIPTORS_SECTION ) ) ); +static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); static NetworkInterface_t * pxMyInterface = NULL; static TaskHandle_t xEMACTaskHandle; -static SemaphoreHandle_t xTxMutex; - -static SemaphoreHandle_t xTxDescSem; +static SemaphoreHandle_t xTxMutex, xTxDescSem; static EthernetPhy_t xPhyObject; static const PhyProperties_t xPHYProperties = { - .ucSpeed = PHY_SPEED_AUTO, - .ucDuplex = PHY_DUPLEX_AUTO, - .ucMDI_X = PHY_MDIX_AUTO, + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + .ucSpeed = PHY_SPEED_AUTO, + .ucDuplex = PHY_DUPLEX_AUTO, + #else + #if ( niEMAC_USE_100MB != 0 ) + .ucSpeed = PHY_SPEED_100, + #else + .ucSpeed = PHY_SPEED_10, + #endif + + #if ( niEMAC_USE_FULL_DUPLEX != 0 ) + .ucDuplex = PHY_DUPLEX_FULL, + #else + .ucDuplex = PHY_DUPLEX_HALF, + #endif + #endif /* if ( niEMAC_AUTO_NEGOTIATION != 0 ) */ + + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) && ( niEMAC_AUTO_CROSS != 0 ) + .ucMDI_X = PHY_MDIX_AUTO, + #elif ( niEMAC_CROSSED_LINK != 0 ) + .ucMDI_X = PHY_MDIX_CROSSED, + #else + .ucMDI_X = PHY_MDIX_DIRECT, + #endif }; /*-----------------------------------------------------------*/ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ EMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( EMAC_CACHE_LINE_SIZE ) __attribute__( ( section( EMAC_BUFFERS_SECTION ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_CACHE_LINE_SIZE ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); configASSERT( xBufferAllocFixedSize == pdTRUE ); @@ -183,9 +243,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net ( void ) memset( pxInterface, '\0', sizeof( *pxInterface ) ); pxInterface->pcName = pcName; pxInterface->pvArgument = ( void * ) xEMACIndex; - pxInterface->pfInitialise = xSTM32_NetworkInterfaceInitialise; - pxInterface->pfOutput = xSTM32_NetworkInterfaceOutput; - pxInterface->pfGetPhyLinkStatus = xSTM32_GetPhyLinkStatus; + pxInterface->pfInitialise = prvNetworkInterfaceInitialise; + pxInterface->pfOutput = prvNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = prvGetPhyLinkStatus; ( void ) FreeRTOS_AddNetworkInterface( pxInterface ); @@ -196,15 +256,15 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /*-----------------------------------------------------------*/ -static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) +static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { ( void ) pxInterface; - BaseType_t xReturn = pdFAIL; + BaseType_t xReturn = pdFALSE; if( xPhyObject.ulLinkStatusMask != 0U ) { - xReturn = pdPASS; + xReturn = pdTRUE; } return xReturn; @@ -212,7 +272,7 @@ static BaseType_t xSTM32_GetPhyLinkStatus( NetworkInterface_t * pxInterface ) /*-----------------------------------------------------------*/ -static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) +static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xInitResult = pdFAIL; BaseType_t xResult; @@ -236,13 +296,18 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte } xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; - xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; - xEthHandle.Init.TxDesc = DMATxDscrTab; - xEthHandle.Init.RxDesc = DMARxDscrTab; - xEthHandle.Init.RxBuffLen = EMAC_DATA_BUFFER_SIZE; + #if ( niEMAC_USE_RMII != 0 ) + xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; + #else + xEthHandle.Init.MediaInterface = HAL_ETH_MII_MODE; + #endif + xEthHandle.Init.TxDesc = xDMADescTx; + xEthHandle.Init.RxDesc = xDMADescRx; + xEthHandle.Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; + configASSERT( xEthHandle.Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); - ( void ) memset( &DMATxDscrTab, 0, sizeof( DMATxDscrTab ) ); - ( void ) memset( &DMARxDscrTab, 0, sizeof( DMARxDscrTab ) ); + ( void ) memset( &xDMADescTx, 0, sizeof( xDMADescTx ) ); + ( void ) memset( &xDMADescRx, 0, sizeof( xDMADescRx ) ); #if defined( STM32F7 ) || defined( STM32F4 ) /* This function doesn't get called in Fxx driver */ @@ -304,13 +369,11 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte prvMACAddressConfig( &xEthHandle, ucMACAddress ); } #else - { if( xEthHandle.Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) { prvMACAddressConfig( &xEthHandle, pxEndPoint->xMACAddress.ucBytes ); } - } - #endif + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ } #if ( ipconfigUSE_IPv6 != 0 ) @@ -340,12 +403,18 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte break; } - if ( xSTM32_GetPhyLinkStatus( pxInterface ) == pdFAIL ) + if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { - xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ + xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #else + /* Use predefined (fixed) configuration. */ + xResult = xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #endif + configASSERT( xResult == 0 ); - if ( xSTM32_GetPhyLinkStatus( pxInterface ) == pdFAIL ) + if ( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { break; } @@ -375,10 +444,8 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte if( xTxMutex == NULL ) { #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - { static StaticSemaphore_t xTxMutexBuf; xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); - } #else xTxMutex = xSemaphoreCreateMutex(); #endif @@ -387,20 +454,22 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte { break; } - vQueueAddToRegistry( xTxMutex, "TXMutex" ); + vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); } if( xTxDescSem == NULL ) { #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - { static StaticSemaphore_t xTxDescSemBuf; - xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf ); - } + xTxDescSem = xSemaphoreCreateCountingStatic( + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT, + &xTxDescSemBuf + ); #else xTxDescSem = xSemaphoreCreateCounting( - ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, - ( UBaseType_t ) ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT ); #endif configASSERT( xTxDescSem != NULL ); @@ -408,32 +477,30 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte { break; } - vQueueAddToRegistry( xTxDescSem, "xTxDescSem" ); + vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); } if( xEMACTaskHandle == NULL ) { #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - { - static StackType_t uxEMACTaskStack[ ( 2 * configMINIMAL_STACK_SIZE ) ]; + static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; static StaticTask_t xEMACTaskTCB; xEMACTaskHandle = xTaskCreateStatic( prvEMACHandlerTask, - "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), /* ipconfigEMAC_TASK_STACK_SIZE */ + niEMAC_TASK_NAME, + niEMAC_TASK_STACK_SIZE, NULL, - ( configMAX_PRIORITIES - 1 ), + niEMAC_TASK_PRIORITY, uxEMACTaskStack, &xEMACTaskTCB ); - } #else xResult = xTaskCreate( prvEMACHandlerTask, - "EMAC", - ( 2 * configMINIMAL_STACK_SIZE ), /* ipconfigEMAC_TASK_STACK_SIZE */ + niEMAC_TASK_NAME, + niEMAC_TASK_STACK_SIZE, NULL, - ( configMAX_PRIORITIES - 1 ), + niEMAC_TASK_PRIORITY, &xEMACTaskHandle ); configASSERT( xResult == pdPASS ); @@ -466,7 +533,7 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte case eMacInitComplete: configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); - if( xSTM32_GetPhyLinkStatus( pxInterface ) == pdPASS ) + if( prvGetPhyLinkStatus( pxInterface ) == pdTRUE ) { xInitResult = pdPASS; } @@ -477,16 +544,17 @@ static BaseType_t xSTM32_NetworkInterfaceInitialise( NetworkInterface_t * pxInte /*-----------------------------------------------------------*/ -static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; configASSERT( pxDescriptor != NULL ); - configASSERT( xReleaseAfterSend != pdFALSE ); /* Zero-Copy Only */ + /* Zero-Copy Only */ + configASSERT( xReleaseAfterSend != pdFALSE ); iptraceNETWORK_INTERFACE_OUTPUT( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ); - if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= EMAC_DATA_BUFFER_SIZE ) ) + if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ) ) { - if( xSTM32_GetPhyLinkStatus( pxInterface ) != pdFAIL ) + if( prvGetPhyLinkStatus( pxInterface ) != pdFAIL ) { static ETH_TxPacketConfig xTxConfig = { .CRCPadCtrl = ETH_CRC_PAD_INSERT, @@ -499,44 +567,18 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac #endif }; - /*ETH_BufferTypeDef xTxBuffer[ ETH_TX_DESC_CNT ]; - memset( &xTxBuffer, 0, sizeof( xTxBuffer ) ); - NetworkBufferDescriptor_t * pxCurDescriptor = pxDescriptor; - xTxConfig.Length = 0; - for( size_t i = 0; i < ETH_TX_DESC_CNT; i++ ) - { - if( pxCurDescriptor == NULL ) - { - break; - } - xTxBuffer[ i ].buffer = ( uint8_t * ) pxCurDescriptor->pucEthernetBuffer; - xTxBuffer[ i ].len = pxCurDescriptor->xDataLength; - xTxConfig.Length += pxCurDescriptor->xDataLength; - if( i > 0 ) - { - xTxBuffer[ i - 1 ].next = &xTxBuffer[ i ]; - } - if( pxCurDescriptor->pxNextBuffer == NULL ) - { - xTxBuffer[ i ].next = NULL; - } - pxCurDescriptor = pxDescriptor->pxNextBuffer; - } - - xTxConfig.TxBuffer = xTxBuffer; - xTxConfig.pData = pxDescriptor;*/ - ETH_BufferTypeDef xTxBuffer = { .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, .len = pxDescriptor->xDataLength, .next = NULL }; + configASSERT( xTxBuffer.len <= ETH_MAX_PACKET_SIZE ); xTxConfig.Length = xTxBuffer.len; xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.pData = pxDescriptor; - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( 200U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) != pdFALSE ) { if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 50U ) ) != pdFALSE ) { @@ -585,7 +627,7 @@ static BaseType_t xSTM32_NetworkInterfaceOutput( NetworkInterface_t * pxInterfac FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Buffer\n" ) ); } - if( xReleaseAfterSend != pdFALSE ) + if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend != pdFALSE ) ) { vReleaseNetworkBufferAndDescriptor( pxDescriptor ); } @@ -612,7 +654,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) { - /* configASSERT( xEthHandle.RxDescList.RxDataLength <= EMAC_DATA_BUFFER_SIZE ); */ + /* configASSERT( xEthHandle.RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); */ if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ @@ -651,7 +693,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) .eEventType = eNetworkRxEvent, .pvData = ( void * ) pxStartDescriptor, }; - if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 100U ) != pdPASS ) + if( xSendEventStructToIPTask( &xRxEvent, niEMAC_MAX_BLOCK_TIME_MS ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); @@ -676,12 +718,12 @@ static UBaseType_t prvNetworkInterfaceInput( void ) ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); } - return ( BaseType_t ) ( xResult > 0 ); + return ( ( BaseType_t ) ( xResult > 0 ) ); } /*-----------------------------------------------------------*/ -static void prvEMACHandlerTask( void * pvParameters ) +static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { ( void ) pvParameters; @@ -690,7 +732,7 @@ static void prvEMACHandlerTask( void * pvParameters ) BaseType_t xResult = 0U; uint32_t ulISREvents = 0U; - if ( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( 100UL ) ) == pdTRUE ) + if ( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdTRUE ) { HAL_StatusTypeDef xHalResult; @@ -790,13 +832,14 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes configASSERT( xHalResult == HAL_OK ); (void) xHalResult; - /* Fxx - ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT | ETH_DMARXDESC_LC | ETH_DMARXDESC_CE | ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE */ + /* Fxx - ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT | ETH_DMARXDESC_LC | ETH_DMARXDESC_CE | ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE */ /* Hxx - ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT | ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE */ if ( pErrorCode == 0 ) { - // ipconfigETHERNET_DRIVER_FILTERS_PACKETS - const eFrameProcessingResult_t xFrameProcessingResult = ipCONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); + /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS, ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES */ + /* ETH_IP_PAYLOAD_UNKNOWN */ + const eFrameProcessingResult_t xFrameProcessingResult = niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); if( xFrameProcessingResult == eProcessBuffer ) { xResult = pdTRUE; @@ -815,11 +858,13 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - BaseType_t xResult = -1; + BaseType_t xResult = pdTRUE; + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) { - xResult = 0; + xResult = pdFALSE; } + return xResult; } @@ -827,11 +872,13 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) { - BaseType_t xResult = -1; + BaseType_t xResult = pdTRUE; + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) { - xResult = 0; + xResult = pdFALSE; } + return xResult; } @@ -842,9 +889,15 @@ static void prvEthernetUpdateConfig( void ) BaseType_t xResult; HAL_StatusTypeDef xHalResult; - if( xSTM32_GetPhyLinkStatus( pxMyInterface ) != pdFAIL ) + if( prvGetPhyLinkStatus( pxMyInterface ) != pdFAIL ) { - xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ + xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #else + /* Use predefined (fixed) configuration. */ + xResult = xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + #endif configASSERT( xResult == 0 ); ETH_MACConfigTypeDef xMACConfig; @@ -879,7 +932,8 @@ static void prvEthernetUpdateConfig( void ) static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * addr ) { - static BaseType_t xMACEntry = ETH_MAC_ADDRESS1; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ + /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ + static BaseType_t xMACEntry = ETH_MAC_ADDRESS1; switch(xMACEntry) { @@ -924,7 +978,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) { if( heth->gState == HAL_ETH_STATE_ERROR ) { - /* fatal bus error occurred */ + /* Fatal bus error occurred */ /* Fxx - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ /* Hxx - ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS */ ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrDma, eSetBits, &xHigherPriorityTaskWoken ); @@ -983,7 +1037,7 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) void HAL_ETH_RxAllocateCallback( uint8_t **buff ) { - const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( 200U ) ); + const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { *buff = pxBufferDescriptor->pucEthernetBuffer; @@ -1001,7 +1055,7 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t NetworkBufferDescriptor_t ** const pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; NetworkBufferDescriptor_t ** const pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); - if ( Length <= EMAC_DATA_BUFFER_SIZE && prvAcceptPacket( pxCurDescriptor ) == pdTRUE ) + if ( Length <= niEMAC_DATA_BUFFER_SIZE && prvAcceptPacket( pxCurDescriptor ) == pdTRUE ) { pxCurDescriptor->xDataLength = Length; #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) @@ -1053,20 +1107,8 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) iptraceNETWORK_INTERFACE_TRANSMIT(); BaseType_t xHigherPriorityTaskWoken = pdFALSE; - /* vTaskNotifyGiveIndexedFromISR( xEMACTaskHandle, TX_INDEX, &xHigherPriorityTaskWoken ); */ ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - - /* if( xBufferAllocFixedSize == pdTRUE ) - { - if( xSemaphoreTakeFromISR( xTxMutex, &xHigherPriorityTaskWoken ) != pdFALSE ) - { - const HAL_StatusTypeDef xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); - ( void ) xSemaphoreGiveFromISR( xTxMutex, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } - } */ } /*-----------------------------------------------------------*/ @@ -1076,16 +1118,6 @@ void HAL_ETH_TxFreeCallback( uint32_t *buff ) NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); ( void ) xSemaphoreGive( xTxDescSem ); - - /* - if( xBufferAllocFixedSize == pdTRUE ) - { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - ( void ) xReleaseNetworkBufferFromISR( pxNetworkBuffer ); - ( void ) xSemaphoreGiveFromISR( xTxDescSem, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } - */ } /*-----------------------------------------------------------*/ From d0d082bd0f0a3bba90ee089f78e3f140d37cafb0 Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 12 Dec 2023 10:19:42 -0500 Subject: [PATCH 21/68] update mac filter and hash table --- .../NetworkInterface/STM32/NetworkInterface.c | 194 ++++++++++++------ 1 file changed, 133 insertions(+), 61 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index eb76aebf16..2042baafed 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -152,6 +152,12 @@ typedef enum /*-----------------------------------------------------------*/ +static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); + +static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); + +static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); + NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); @@ -170,9 +176,9 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); -static void prvEthernetUpdateConfig( void ); +static void prvEthernetUpdateConfig( ETH_HandleTypeDef * pxEthHandle ); -static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * Addr ); +static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t * Addr ); /*-----------------------------------------------------------*/ @@ -219,6 +225,74 @@ static const PhyProperties_t xPHYProperties = { /*-----------------------------------------------------------*/ +/* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ +static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ) +{ + uint32_t ulCRC32 = 0xFFFFFFFF; + + for( UBaseType_t i = 0; i < 6; ++i ) + { + ulCRC32 ^= ( uint32_t ) pucMAC[ i ]; + + for( UBaseType_t j = 0; j < 8; ++j ) + { + ulCRC32 >>= 1; + if( ulCRC32 & 1 ) + { + /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ + ulCRC32 ^= __RBIT( 0x04C11DB7 ); + } + } + } + + ulCRC32 = ~( ulCRC32 ); + return ulCRC32; +} + +/*-----------------------------------------------------------*/ + +/* Compute the hash value of a given MAC address to index the bits in the Hash Table + * Registers (ETH_MACHT0R and ETH_MACHT1R) */ +static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ) +{ + /* Calculate the 32-bit CRC for the MAC */ + const uint32_t ulCRC32 = prvComputeCRC32_MAC( pucMAC ); + + /* Perform bitwise reversal on the CRC32 */ + const uint32_t ulHash = __RBIT( ulCRC32 ); + + /* Take the upper 6 bits of the above result */ + return ( ulHash >> 26 ); +} + +/*-----------------------------------------------------------*/ + +/* Update the Hash Table Registers + * (ETH_MACHT0R and ETH_MACHT1R) with hash value of the given MAC address */ +static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) +{ + static uint32_t ulHashTable[2]; + + const uint32_t ulHash = prvComputeEthernet_MACHash( pucMAC ); + + /* Use the upper (MACHT1R) or lower (MACHT0R) Hash Table Registers + * to set the required bit based on the ulHash */ + if( ulHash < 32 ) + { + ulHashTable[0] = ulHash; + } + else + { + ulHashTable[1] = ulHash; + } + + const HAL_StatusTypeDef xHalResult = HAL_ETH_SetHashTable( pxEthHandle, ( uint8_t * ) &ulHashTable ); + configASSERT( xHalResult == HAL_OK ); + (void) xHalResult; +} + +/*-----------------------------------------------------------*/ + void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_CACHE_LINE_SIZE ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); @@ -324,20 +398,14 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - #if 0 - ETH_MACFilterConfigTypeDef xFilterConfig; - xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); - - xFilterConfig.HashUnicast = ENABLE; - xFilterConfig.HashMulticast = ENABLE; - xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); + ETH_MACFilterConfigTypeDef xFilterConfig; + xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); - const uint32_t ulHashTable = 0x00; - xHalResult = HAL_ETH_SetHashTable( &xEthHandle, &ulHashTable ); - configASSERT( xHalResult == HAL_OK ); - #endif + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.HashMulticast = ENABLE; + xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); #if ( ipconfigUSE_MDNS != 0 ) prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MacAddress.ucBytes ); @@ -489,7 +557,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac prvEMACHandlerTask, niEMAC_TASK_NAME, niEMAC_TASK_STACK_SIZE, - NULL, + ( void * ) &xEthHandle, niEMAC_TASK_PRIORITY, uxEMACTaskStack, &xEMACTaskTCB @@ -499,7 +567,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac prvEMACHandlerTask, niEMAC_TASK_NAME, niEMAC_TASK_STACK_SIZE, - NULL, + ( void * ) &xEthHandle, niEMAC_TASK_PRIORITY, &xEMACTaskHandle ); @@ -725,7 +793,8 @@ static UBaseType_t prvNetworkInterfaceInput( void ) static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { - ( void ) pvParameters; + ETH_HandleTypeDef * pxEthHandle = ( ETH_HandleTypeDef * ) pvParameters; + configASSERT( pxEthHandle ); for( ;; ) { @@ -745,7 +814,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) { - xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xHalResult = HAL_ETH_ReleaseTxPacket( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); ( void ) xSemaphoreGive( xTxMutex ); } @@ -754,9 +823,9 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) { - xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); + xHalResult = HAL_ETH_ReleaseTxPacket( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); - while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > xEthHandle.TxDescList.BuffersInUse ) + while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > pxEthHandle->TxDescList.BuffersInUse ) { ( void ) xSemaphoreGive( xTxDescSem ); } @@ -773,13 +842,13 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrEth ) != 0 ) { - /* xEthHandle.gState */ - /* xEthHandle.ErrorCode */ + /* pxEthHandle->gState */ + /* pxEthHandle->ErrorCode */ } if( ( ulISREvents & eMacEventErrMac ) != 0 ) { - /* xEthHandle.MACErrorCode */ + /* pxEthHandle->MACErrorCode */ } if( ( ulISREvents & eMacEventErrDma ) != 0 ) @@ -787,23 +856,23 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) /* TODO: Does this recover from fatal bus error? */ if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 5000U ) ) != pdFALSE ) { - /* xEthHandle.DMAErrorCode */ - xEthHandle.gState = HAL_ETH_STATE_STARTED; - xHalResult = HAL_ETH_Stop_IT( &xEthHandle ); + /* pxEthHandle->DMAErrorCode */ + pxEthHandle->gState = HAL_ETH_STATE_STARTED; + xHalResult = HAL_ETH_Stop_IT( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - configASSERT( xEthHandle.RxDescList.ItMode == 0U); - xHalResult = HAL_ETH_DeInit( &xEthHandle ); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_READY ); + configASSERT( pxEthHandle->RxDescList.ItMode == 0U); + xHalResult = HAL_ETH_DeInit( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_RESET ); - xHalResult = HAL_ETH_Init( &xEthHandle ); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_RESET ); + xHalResult = HAL_ETH_Init( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); - configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - xHalResult = HAL_ETH_Start_IT( &xEthHandle ); + configASSERT( pxEthHandle->ErrorCode == HAL_ETH_ERROR_NONE ); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_READY ); + xHalResult = HAL_ETH_Start_IT( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); - configASSERT( xEthHandle.RxDescList.ItMode == 1U); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); + configASSERT( pxEthHandle->RxDescList.ItMode == 1U); xSemaphoreGive( xTxMutex ); } } @@ -813,9 +882,9 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { - if( xEthHandle.gState != HAL_ETH_STATE_BUSY ) + if( pxEthHandle->gState != HAL_ETH_STATE_BUSY ) { - prvEthernetUpdateConfig(); + prvEthernetUpdateConfig( pxEthHandle ); } } } @@ -884,7 +953,7 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin /*-----------------------------------------------------------*/ -static void prvEthernetUpdateConfig( void ) +static void prvEthernetUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) { BaseType_t xResult; HAL_StatusTypeDef xHalResult; @@ -901,22 +970,22 @@ static void prvEthernetUpdateConfig( void ) configASSERT( xResult == 0 ); ETH_MACConfigTypeDef xMACConfig; - xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); + xHalResult = HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); configASSERT( xHalResult == HAL_OK ); xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; - xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &xMACConfig ); + xHalResult = HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ); configASSERT( xHalResult == HAL_OK ); - xHalResult = HAL_ETH_Start_IT( &xEthHandle ); + xHalResult = HAL_ETH_Start_IT( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); } else { /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ - xHalResult = HAL_ETH_Stop_IT( &xEthHandle ); + xHalResult = HAL_ETH_Stop_IT( pxEthHandle ); configASSERT( xHalResult == HAL_OK ); #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) @@ -930,25 +999,28 @@ static void prvEthernetUpdateConfig( void ) /*-----------------------------------------------------------*/ -static void prvMACAddressConfig( ETH_HandleTypeDef * heth, const uint8_t * addr ) +static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t * addr ) { /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - static BaseType_t xMACEntry = ETH_MAC_ADDRESS1; + static UBaseType_t xMACEntry = ETH_MAC_ADDRESS1; switch(xMACEntry) { case ETH_MAC_ADDRESS1: - HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS1, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS1, addr ); + prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS2; break; case ETH_MAC_ADDRESS2: - HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS2, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS2, addr ); + prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS3; break; case ETH_MAC_ADDRESS3: - HAL_ETH_SetSourceMACAddrMatch( &xEthHandle, ETH_MAC_ADDRESS3, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS3, addr ); + prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS0; break; @@ -969,14 +1041,14 @@ void ETH_IRQHandler( void ) /*-----------------------------------------------------------*/ -void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) +void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *pxEthHandle ) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if( heth->ErrorCode & HAL_ETH_ERROR_DMA ) + if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA ) { - if( heth->DMAErrorCode ) + if( pxEthHandle->DMAErrorCode ) { - if( heth->gState == HAL_ETH_STATE_ERROR ) + if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Fatal bus error occurred */ /* Fxx - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ @@ -988,12 +1060,12 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) /* Fxx - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ /* Hxx - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ #if defined( STM32F4 ) || defined ( STM32F7 ) - if( ( heth->DMAErrorCode & ETH_DMASR_TBUS ) == ETH_DMASR_TBUS) + if( ( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) == ETH_DMASR_TBUS) { ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); } - if( ( heth->DMAErrorCode & ETH_DMASR_RBUS ) == ETH_DMASR_RBUS) + if( ( pxEthHandle->DMAErrorCode & ETH_DMASR_RBUS ) == ETH_DMASR_RBUS) { ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); } @@ -1002,9 +1074,9 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) } } - if( heth->ErrorCode & HAL_ETH_ERROR_MAC ) + if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC ) { - if( heth->MACErrorCode ) + if( pxEthHandle->MACErrorCode ) { ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); } @@ -1015,11 +1087,11 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *heth ) /*-----------------------------------------------------------*/ -void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) +void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) { static size_t uxMostRXDescsUsed = 0U; - const size_t uxRxUsed = heth->RxDescList.RxDescCnt; + const size_t uxRxUsed = pxEthHandle->RxDescList.RxDescCnt; if( uxMostRXDescsUsed < uxRxUsed ) { @@ -1093,11 +1165,11 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t /*-----------------------------------------------------------*/ -void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) { static size_t uxMostTXDescsUsed = 0U; - const size_t uxTxUsed = heth->TxDescList.BuffersInUse; + const size_t uxTxUsed = pxEthHandle->TxDescList.BuffersInUse; if( uxMostTXDescsUsed < uxTxUsed ) { From a20e0447cdc17474dcb306cf612f7ded7bbe29a4 Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 12 Dec 2023 14:09:55 -0500 Subject: [PATCH 22/68] fix compilation issue --- .../NetworkInterface/STM32/NetworkInterface.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 2042baafed..4e28c1d3e3 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -286,7 +286,7 @@ static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t ulHashTable[1] = ulHash; } - const HAL_StatusTypeDef xHalResult = HAL_ETH_SetHashTable( pxEthHandle, ( uint8_t * ) &ulHashTable ); + const HAL_StatusTypeDef xHalResult = HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); configASSERT( xHalResult == HAL_OK ); (void) xHalResult; } @@ -398,14 +398,16 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - ETH_MACFilterConfigTypeDef xFilterConfig; - xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); + #if 0 + ETH_MACFilterConfigTypeDef xFilterConfig; + xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); - xFilterConfig.HashUnicast = ENABLE; - xFilterConfig.HashMulticast = ENABLE; - xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.HashMulticast = ENABLE; + xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); + configASSERT( xHalResult == HAL_OK ); + #endif #if ( ipconfigUSE_MDNS != 0 ) prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MacAddress.ucBytes ); From 36508bf78150e2633fc0fd495cff2cbb99a41f15 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Wed, 13 Dec 2023 14:27:56 +0300 Subject: [PATCH 23/68] prvMACAddressConfig: fix implicit discarding of const qualifier --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 4e28c1d3e3..6199c0ae6a 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1009,19 +1009,19 @@ static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t switch(xMACEntry) { case ETH_MAC_ADDRESS1: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS1, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS1, ( uint8_t* ) addr ); prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS2; break; case ETH_MAC_ADDRESS2: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS2, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS2, ( uint8_t* ) addr ); prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS3; break; case ETH_MAC_ADDRESS3: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS3, addr ); + HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS3, ( uint8_t* ) addr ); prvSetMAC_HashFilter( pxEthHandle, addr ); xMACEntry = ETH_MAC_ADDRESS0; break; From 7ef89d4e2a1b4ced6160fef92c8a465b6c621136 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Wed, 13 Dec 2023 14:29:22 +0300 Subject: [PATCH 24/68] ETH_IRQHandler: add tracing, process all interrupt flags before context switch --- .../NetworkInterface/STM32/NetworkInterface.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 4e28c1d3e3..a26c0ccce4 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1036,9 +1036,16 @@ static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t /*-----------------------------------------------------------*/ +static BaseType_t xSwitchRequired; + void ETH_IRQHandler( void ) { + traceISR_ENTER(); + + xSwitchRequired = pdFALSE; HAL_ETH_IRQHandler( &xEthHandle ); + + portYIELD_FROM_ISR( xSwitchRequired ); } /*-----------------------------------------------------------*/ @@ -1084,7 +1091,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *pxEthHandle ) } } - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; } /*-----------------------------------------------------------*/ @@ -1104,7 +1111,7 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) BaseType_t xHigherPriorityTaskWoken = pdFALSE; ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventRx, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; } /*-----------------------------------------------------------*/ @@ -1182,7 +1189,7 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) BaseType_t xHigherPriorityTaskWoken = pdFALSE; ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; } /*-----------------------------------------------------------*/ From 9c602a22b914c0463c6baf2caf92676e1ce1ed2a Mon Sep 17 00:00:00 2001 From: Holden <68555040+holden-zenith@users.noreply.github.com> Date: Wed, 13 Dec 2023 23:23:11 -0500 Subject: [PATCH 25/68] prvEMACHandlerTask: fix NetworkDown event --- .../NetworkInterface/STM32/NetworkInterface.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index e30fccab12..20f835e8f6 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -884,10 +884,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { - if( pxEthHandle->gState != HAL_ETH_STATE_BUSY ) - { - prvEthernetUpdateConfig( pxEthHandle ); - } + prvEthernetUpdateConfig( pxEthHandle ); } } } @@ -960,8 +957,13 @@ static void prvEthernetUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) BaseType_t xResult; HAL_StatusTypeDef xHalResult; - if( prvGetPhyLinkStatus( pxMyInterface ) != pdFAIL ) + if( prvGetPhyLinkStatus( pxMyInterface ) != pdFALSE ) { + if(HAL_ETH_GetState(pxEthHandle) == HAL_ETH_STATE_STARTED) { + xHalResult = HAL_ETH_Stop_IT(pxEthHandle); + configASSERT(xHalResult == HAL_OK); + } + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); From f59a7710ff261e6d48597358cd45825d5102d9e0 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 18 Dec 2023 14:34:25 -0500 Subject: [PATCH 26/68] fix ipconfigUSE_LINKED_RX_MESSAGES == 0 --- .../NetworkInterface/STM32/NetworkInterface.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 20f835e8f6..73533f4cb6 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -721,6 +721,8 @@ static UBaseType_t prvNetworkInterfaceInput( void ) NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; + IPStackEvent_t xRxEvent; + xRxEvent.eEventType = eNetworkRxEvent; while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) { @@ -753,16 +755,13 @@ static UBaseType_t prvNetworkInterfaceInput( void ) FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); } - #endif + #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ } #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) if( xResult > 0 ) { - const IPStackEvent_t xRxEvent = { - .eEventType = eNetworkRxEvent, - .pvData = ( void * ) pxStartDescriptor, - }; + xRxEvent.pvData = ( void * ) pxStartDescriptor; if( xSendEventStructToIPTask( &xRxEvent, niEMAC_MAX_BLOCK_TIME_MS ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); @@ -775,7 +774,7 @@ static UBaseType_t prvNetworkInterfaceInput( void ) } while( pxDescriptorToClear != NULL ); } } - #endif + #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ if( xResult == 0 ) { From 80d4380d6a54f3c1a217a1305ef806e1b2076b4b Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 22 Dec 2023 17:12:59 -0500 Subject: [PATCH 27/68] remove test files --- .../STM32/Fxx/STM32F767ZITX_FLASH.ld | 205 ------------------ .../portable/NetworkInterface/STM32/Fxx/mpu.c | 31 --- 2 files changed, 236 deletions(-) delete mode 100644 source/portable/NetworkInterface/STM32/Fxx/STM32F767ZITX_FLASH.ld delete mode 100644 source/portable/NetworkInterface/STM32/Fxx/mpu.c diff --git a/source/portable/NetworkInterface/STM32/Fxx/STM32F767ZITX_FLASH.ld b/source/portable/NetworkInterface/STM32/Fxx/STM32F767ZITX_FLASH.ld deleted file mode 100644 index 838406daf1..0000000000 --- a/source/portable/NetworkInterface/STM32/Fxx/STM32F767ZITX_FLASH.ld +++ /dev/null @@ -1,205 +0,0 @@ -/* -****************************************************************************** -** -** @file : LinkerScript.ld -** -** @author : Auto-generated by STM32CubeIDE -** -** Abstract : Linker script for NUCLEO-F767ZI Board embedding STM32F767ZITx Device from stm32f7 series -** 2048Kbytes FLASH -** 512Kbytes RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used -** -** Target : STMicroelectronics STM32 -** -** Distribution: The file is distributed as is, without any warranty -** of any kind. -** -****************************************************************************** -** @attention -** -** Copyright (c) 2022 STMicroelectronics. -** All rights reserved. -** -** This software is licensed under terms that can be found in the LICENSE file -** in the root directory of this software component. -** If no LICENSE file comes with this software, it is provided AS-IS. -** -****************************************************************************** -*/ - -/* Entry Point */ -ENTRY(Reset_Handler) - -/* Highest address of the user mode stack */ -_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ - -_Min_Heap_Size = 8K; /* required amount of heap */ -_Min_Stack_Size = 4K; /* required amount of stack */ - -/* Memories definition */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 447K - RAM_NO_CACHE (rwx) : ORIGIN = 0x2006FC00, LENGTH = 65K -} - -/* Sections */ -SECTIONS -{ - /* The startup code into "FLASH" Rom type memory */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data into "FLASH" Rom type memory */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - /* Constant data into "FLASH" Rom type memory */ - .rodata : - { - . = ALIGN(4); - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - . = ALIGN(4); - } >FLASH - - .ARM.extab : { - . = ALIGN(4); - *(.ARM.extab* .gnu.linkonce.armextab.*) - . = ALIGN(4); - } >FLASH - - .ARM : { - . = ALIGN(4); - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - . = ALIGN(4); - } >FLASH - - .preinit_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - . = ALIGN(4); - } >FLASH - - .init_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - . = ALIGN(4); - } >FLASH - - .fini_array : - { - . = ALIGN(4); - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT(.fini_array.*))) - KEEP (*(.fini_array*)) - PROVIDE_HIDDEN (__fini_array_end = .); - . = ALIGN(4); - } >FLASH - - /* Used by the startup to initialize data */ - _sidata = LOADADDR(.data); - - /* Initialized data sections into "RAM" Ram type memory */ - .data : - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - *(.RamFunc) /* .RamFunc sections */ - *(.RamFunc*) /* .RamFunc* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - - } >RAM AT> FLASH - - /* Uninitialized data section into "RAM" Ram type memory */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss section */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ - ._user_heap_stack : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - .EthDescriptorsBlock (NOLOAD) : - { - . = ALIGN(1K); - __ETH_DESCRIPTORS_START = .; - *(.RxDescripSection) - *(.TxDescripSection) - . = ALIGN(1K); - __ETH_DESCRIPTORS_END = .; - } >RAM_NO_CACHE - - .EthBuffersBlock (NOLOAD) : - { - . = ALIGN(64K); - __ETH_BUFFERS_START = .; - *(.EthBuffersSection) - . = ALIGN(64K); - __ETH_BUFFERS_END = .; - } >RAM_NO_CACHE - - /* Remove information from the compiler libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } -} diff --git a/source/portable/NetworkInterface/STM32/Fxx/mpu.c b/source/portable/NetworkInterface/STM32/Fxx/mpu.c deleted file mode 100644 index d84f05dd41..0000000000 --- a/source/portable/NetworkInterface/STM32/Fxx/mpu.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "main.h" -#include "mpu.h" - -void MPU_Config(void) -{ - LL_MPU_Disable(); - - extern int __ETH_DESCRIPTORS_START, __ETH_BUFFERS_START; - - LL_MPU_ConfigRegion( - LL_MPU_REGION_NUMBER0, - 0x0, - ( uint32_t )&__ETH_DESCRIPTORS_START, - LL_MPU_REGION_SIZE_1KB|LL_MPU_TEX_LEVEL0|LL_MPU_REGION_FULL_ACCESS|\ - LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ - LL_MPU_ACCESS_BUFFERABLE - ); - LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0); - - LL_MPU_ConfigRegion( - LL_MPU_REGION_NUMBER1, - 0x0, - ( uint32_t )&__ETH_BUFFERS_START, - LL_MPU_REGION_SIZE_64KB|LL_MPU_TEX_LEVEL1|LL_MPU_REGION_FULL_ACCESS|\ - LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|\ - LL_MPU_ACCESS_NOT_BUFFERABLE - ); - LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER1); - - LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT); -} From e40ea1b4af725abeb43a1da52dc236181417d04a Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 5 Jan 2024 16:31:46 -0500 Subject: [PATCH 28/68] allow access to pcLOCAL_ALL_NODES_MULTICAST_MAC in network interfaces --- source/FreeRTOS_ND.c | 2 +- source/include/FreeRTOS_ND.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index dcbf4d6ebd..ab30a6f769 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -79,7 +79,7 @@ /* coverity[misra_c_2012_rule_8_9_violation] */ static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_IP[ ipSIZE_OF_IPv6_ADDRESS ] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; /* ff02:1 */ /** @brief All nodes on the local network segment: MAC address. */ - static const uint8_t pcLOCAL_ALL_NODES_MULTICAST_MAC[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 }; + const MACAddress_t pcLOCAL_ALL_NODES_MULTICAST_MAC = { { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } }; /** @brief See if the MAC-address can be resolved because it is a multi-cast address. */ static eARPLookupResult_t prvMACResolve( const IPv6_Address_t * pxAddressToLookup, diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index bdbabdec71..06fbb1d81f 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -61,6 +61,9 @@ uint8_t ucValid; /**< pdTRUE: xMACAddress is valid, pdFALSE: waiting for ND reply */ } NDCacheRow_t; +/** @brief All nodes on the local network segment: MAC address 33:33:00:00:00:01. */ + extern const MACAddress_t pcLOCAL_ALL_NODES_MULTICAST_MAC; + /* * If ulIPAddress is already in the ND cache table then reset the age of the * entry back to its maximum value. If ulIPAddress is not already in the ND From e09a9e73b3c475a8d98277e0e6e2910f2f515225 Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 5 Jan 2024 16:32:03 -0500 Subject: [PATCH 29/68] some restructuring --- .../NetworkInterface/STM32/NetworkInterface.c | 1303 +++++++++-------- 1 file changed, 700 insertions(+), 603 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 73533f4cb6..5e64f527ff 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -63,7 +63,9 @@ #error Unknown STM32 Family for NetworkInterface #endif -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Config Checks */ +/*===========================================================================*/ #if ( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) #if ( ipconfigPORT_SUPPRESS_WARNING == 0 ) @@ -77,14 +79,18 @@ #endif #endif -/*-----------------------------------------------------------*/ +#if ( configUSE_TASK_NOTIFICATIONS == 0 ) + #error Task Notifications must be enabled for NetworkInterface +#endif -#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) - #define niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer -#else - #define niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) +#ifndef HAL_ETH_MODULE_ENABLED + #error HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface #endif +/*===========================================================================*/ +/* Macros */ +/*===========================================================================*/ + #define niEMAC_TX_DESC_SECTION ".TxDescripSection" #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" @@ -100,33 +106,33 @@ #define niEMAC_CACHE_LINE_SIZE 32U #endif -#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ~portBYTE_ALIGNMENT_MASK ) -#define niEMAC_TOTAL_ALIGNMENT_MASK ( niEMAC_CACHE_LINE_SIZE - 1U ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ( ( uint32_t ) ~portBYTE_ALIGNMENT_MASK ) ) +#define niEMAC_TOTAL_ALIGNMENT_MASK ( niEMAC_CACHE_LINE_SIZE - 1U ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) -#define niEMAC_MAX_BLOCK_TIME_MS 100U -#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U +#define niEMAC_MAX_BLOCK_TIME_MS 100U +#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U -#define niEMAC_TASK_NAME "EMAC_STM32" +#define niEMAC_TASK_NAME "EMAC_STM32" #define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) -#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) +#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" -#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" +#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" -#define niEMAC_AUTO_NEGOTIATION 1 -#define niEMAC_AUTO_CROSS 1 +/* #define niEMAC_PHY_COUNT 1 */ -#if ( niEMAC_AUTO_NEGOTIATION == 0 ) - #define niEMAC_CROSSED_LINK 1 - #define niEMAC_USE_100MB 1 - #define niEMAC_USE_FULL_DUPLEX 1 -#endif +#define niEMAC_AUTO_NEGOTIATION 1 +#define niEMAC_USE_100MB ( 1 && ( niEMAC_AUTO_NEGOTIATION == 0 ) ) +#define niEMAC_USE_FULL_DUPLEX ( 1 && ( niEMAC_AUTO_NEGOTIATION == 0 ) ) +#define niEMAC_AUTO_CROSS ( 1 && ( niEMAC_AUTO_NEGOTIATION != 0 ) ) +#define niEMAC_CROSSED_LINK ( 1 && ( niEMAC_AUTO_CROSS == 0 ) ) #define niEMAC_USE_RMII 1 - -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Enums */ +/*===========================================================================*/ /* Interrupt events to process: reception, transmission and error handling. */ typedef enum { @@ -137,7 +143,7 @@ typedef enum { eMacEventErrDma = 1 << 4, eMacEventErrEth = 1 << 5, eMacEventErrMac = 1 << 6, - eMacEventAll = (1 << 7) - 1, + eMacEventAll = ( 1 << 7 ) - 1, } eMAC_IF_EVENT; typedef enum @@ -150,185 +156,87 @@ typedef enum eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; -/*-----------------------------------------------------------*/ - -static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); - -static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); - -static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); +/*===========================================================================*/ +/* Static Function Declarations */ +/*===========================================================================*/ -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); +static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); - static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); +/* static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); */ +/* static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); */ -static UBaseType_t prvNetworkInterfaceInput( void ); - +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ); static portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ) __NO_RETURN; +static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ); -static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ); - -static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); - -static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); +static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ); +static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); +static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); +static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); +static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucAddr ); -static void prvEthernetUpdateConfig( ETH_HandleTypeDef * pxEthHandle ); +/* static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ); */ +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ); -static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t * Addr ); +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Static Variable Declarations */ +/*===========================================================================*/ static ETH_HandleTypeDef xEthHandle; -static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); - -static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); - -static NetworkInterface_t * pxMyInterface = NULL; +static NetworkInterface_t * pxMyInterface; +static EthernetPhy_t xPhyObject; static TaskHandle_t xEMACTaskHandle; - static SemaphoreHandle_t xTxMutex, xTxDescSem; -static EthernetPhy_t xPhyObject; - -static const PhyProperties_t xPHYProperties = { - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) - .ucSpeed = PHY_SPEED_AUTO, - .ucDuplex = PHY_DUPLEX_AUTO, - #else - #if ( niEMAC_USE_100MB != 0 ) - .ucSpeed = PHY_SPEED_100, - #else - .ucSpeed = PHY_SPEED_10, - #endif - - #if ( niEMAC_USE_FULL_DUPLEX != 0 ) - .ucDuplex = PHY_DUPLEX_FULL, - #else - .ucDuplex = PHY_DUPLEX_HALF, - #endif - #endif /* if ( niEMAC_AUTO_NEGOTIATION != 0 ) */ - - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) && ( niEMAC_AUTO_CROSS != 0 ) - .ucMDI_X = PHY_MDIX_AUTO, - #elif ( niEMAC_CROSSED_LINK != 0 ) - .ucMDI_X = PHY_MDIX_CROSSED, - #else - .ucMDI_X = PHY_MDIX_DIRECT, - #endif -}; - -/*-----------------------------------------------------------*/ - -/* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ -static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ) -{ - uint32_t ulCRC32 = 0xFFFFFFFF; - - for( UBaseType_t i = 0; i < 6; ++i ) - { - ulCRC32 ^= ( uint32_t ) pucMAC[ i ]; - - for( UBaseType_t j = 0; j < 8; ++j ) - { - ulCRC32 >>= 1; - if( ulCRC32 & 1 ) - { - /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ - ulCRC32 ^= __RBIT( 0x04C11DB7 ); - } - } - } - - ulCRC32 = ~( ulCRC32 ); - return ulCRC32; -} - -/*-----------------------------------------------------------*/ +static volatile BaseType_t xSwitchRequired; -/* Compute the hash value of a given MAC address to index the bits in the Hash Table - * Registers (ETH_MACHT0R and ETH_MACHT1R) */ -static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ) -{ - /* Calculate the 32-bit CRC for the MAC */ - const uint32_t ulCRC32 = prvComputeCRC32_MAC( pucMAC ); +static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; - /* Perform bitwise reversal on the CRC32 */ - const uint32_t ulHash = __RBIT( ulCRC32 ); +/*===========================================================================*/ +/* Phy Hooks */ +/*===========================================================================*/ - /* Take the upper 6 bits of the above result */ - return ( ulHash >> 26 ); -} - -/*-----------------------------------------------------------*/ - -/* Update the Hash Table Registers - * (ETH_MACHT0R and ETH_MACHT1R) with hash value of the given MAC address */ -static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) +static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - static uint32_t ulHashTable[2]; - - const uint32_t ulHash = prvComputeEthernet_MACHash( pucMAC ); + BaseType_t xResult = pdTRUE; - /* Use the upper (MACHT1R) or lower (MACHT0R) Hash Table Registers - * to set the required bit based on the ulHash */ - if( ulHash < 32 ) - { - ulHashTable[0] = ulHash; - } - else + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) { - ulHashTable[1] = ulHash; + xResult = pdFALSE; } - const HAL_StatusTypeDef xHalResult = HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); - configASSERT( xHalResult == HAL_OK ); - (void) xHalResult; + return xResult; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_CACHE_LINE_SIZE ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); - - configASSERT( xBufferAllocFixedSize == pdTRUE ); + BaseType_t xResult = pdTRUE; - for( size_t ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++ul ) + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) { - pxNetworkBuffers[ ul ].pucEthernetBuffer = &( ucNetworkPackets[ ul ][ ipBUFFER_PADDING ] ); - *( ( uint32_t * ) &( ucNetworkPackets[ ul ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ ul ] ) ); + xResult = pdFALSE; } -} - -/*-----------------------------------------------------------*/ - -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) -{ - static char pcName[ 17 ]; - - ( void ) snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); - - ( void ) memset( pxInterface, '\0', sizeof( *pxInterface ) ); - pxInterface->pcName = pcName; - pxInterface->pvArgument = ( void * ) xEMACIndex; - pxInterface->pfInitialise = prvNetworkInterfaceInitialise; - pxInterface->pfOutput = prvNetworkInterfaceOutput; - pxInterface->pfGetPhyLinkStatus = prvGetPhyLinkStatus; - ( void ) FreeRTOS_AddNetworkInterface( pxInterface ); - - pxMyInterface = pxInterface; - - return pxInterface; + return xResult; } -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Network Interface Access Hooks */ +/*===========================================================================*/ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { @@ -336,6 +244,8 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) BaseType_t xReturn = pdFALSE; + /* const BaseType_t xEMACIndex = *( ( BaseType_t * ) pxInterface->pvArgument ); */ + if( xPhyObject.ulLinkStatusMask != 0U ) { xReturn = pdTRUE; @@ -344,15 +254,13 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) return xReturn; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xInitResult = pdFAIL; - BaseType_t xResult; - HAL_StatusTypeDef xHalResult; - static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; switch( xMacInitStatus ) { @@ -361,95 +269,24 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac break; case eMacEthInit: - xEthHandle.Instance = ETH; - - NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); - if( pxEndPoint == NULL ) + if( prvEthConfigInit( pxEthHandle, pxInterface ) == pdFALSE ) { break; } - xEthHandle.Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; - #if ( niEMAC_USE_RMII != 0 ) - xEthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; - #else - xEthHandle.Init.MediaInterface = HAL_ETH_MII_MODE; - #endif - xEthHandle.Init.TxDesc = xDMADescTx; - xEthHandle.Init.RxDesc = xDMADescRx; - xEthHandle.Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; - configASSERT( xEthHandle.Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); - - ( void ) memset( &xDMADescTx, 0, sizeof( xDMADescTx ) ); - ( void ) memset( &xDMADescRx, 0, sizeof( xDMADescRx ) ); - - #if defined( STM32F7 ) || defined( STM32F4 ) - /* This function doesn't get called in Fxx driver */ - HAL_ETH_SetMDIOClockRange( &xEthHandle ); - #endif - - xHalResult = HAL_ETH_Init( &xEthHandle ); - if( xHalResult != HAL_OK ) - { - /* &xEthHandle != NULL - xEthHandle.ErrorCode == HAL_ETH_ERROR_TIMEOUT */ - break; - } - configASSERT( xEthHandle.ErrorCode == HAL_ETH_ERROR_NONE ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_READY ); - - #if 0 - ETH_MACFilterConfigTypeDef xFilterConfig; - xHalResult = HAL_ETH_GetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); - - xFilterConfig.HashUnicast = ENABLE; - xFilterConfig.HashMulticast = ENABLE; - xHalResult = HAL_ETH_SetMACFilterConfig( &xEthHandle, &xFilterConfig ); - configASSERT( xHalResult == HAL_OK ); - #endif - - #if ( ipconfigUSE_MDNS != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MacAddress.ucBytes ); - #if ( ipconfigUSE_IPv6 != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xMDNS_MACAddressIPv6.ucBytes ); - #endif - #endif - - #if ( ipconfigUSE_LLMNR != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MacAddress.ucBytes ); - #if ( ipconfigUSE_IPv6 != 0 ) - prvMACAddressConfig( &xEthHandle, ( uint8_t * ) xLLMNR_MacAddressIPv6.ucBytes ); - #endif - #endif - - for(; pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + /* { - #if ( ipconfigUSE_IPv6 != 0 ) - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { - 0x33, - 0x33, - 0xff, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - }; - prvMACAddressConfig( &xEthHandle, ucMACAddress ); - } - #else - if( xEthHandle.Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) - { - prvMACAddressConfig( &xEthHandle, pxEndPoint->xMACAddress.ucBytes ); - } - #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + ETH_DMAConfigTypeDef xDMAConfig; + ( void ) HAL_ETH_GetDMAConfig( pxEthHandle, &xDMAConfig ); + xDMAConfig. + if( HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ) != HAL_OK ) + { + break; + } } + */ - #if ( ipconfigUSE_IPv6 != 0 ) - const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { 0x33, 0x33, 0, 0, 0, 0x01 }; - prvMACAddressConfig( &xEthHandle, ucMACAddress ); - #endif + prvInitMACAddresses( pxEthHandle, pxInterface ); xMacInitStatus = eMacPhyInit; /* fallthrough */ @@ -457,8 +294,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac case eMacPhyInit: vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); - xResult = xPhyDiscover( &xPhyObject ); - if( xResult == 0 ) + if( xPhyDiscover( &xPhyObject ) == 0 ) { break; } @@ -467,42 +303,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacPhyStart: - xResult = xPhyConfigure( &xPhyObject, &xPHYProperties ); - if( xResult != 0 ) - { - break; - } - - if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) - { - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) - /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ - xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - #else - /* Use predefined (fixed) configuration. */ - xResult = xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - #endif - - configASSERT( xResult == 0 ); - if ( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) - { - break; - } - } - - ETH_MACConfigTypeDef xMACConfig; - xHalResult = HAL_ETH_GetMACConfig( &xEthHandle , &xMACConfig ); - configASSERT( xHalResult == HAL_OK ); - if( xHalResult != HAL_OK ) - { - break; - } - xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; - xMACConfig.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); - xHalResult = HAL_ETH_SetMACConfig( &xEthHandle, &xMACConfig ); - configASSERT( xHalResult == HAL_OK ); - if( xHalResult != HAL_OK ) + if( prvPhyStart( pxEthHandle, pxInterface ) == pdFALSE ) { break; } @@ -511,98 +312,27 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacTaskStart: - if( xTxMutex == NULL ) - { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - static StaticSemaphore_t xTxMutexBuf; - xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); - #else - xTxMutex = xSemaphoreCreateMutex(); - #endif - configASSERT( xTxMutex != NULL ); - if( xTxMutex == NULL ) - { - break; - } - vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); - } - - if( xTxDescSem == NULL ) + if( prvEMACTaskStart( pxEthHandle ) == pdFALSE ) { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - static StaticSemaphore_t xTxDescSemBuf; - xTxDescSem = xSemaphoreCreateCountingStatic( - ( UBaseType_t ) ETH_TX_DESC_CNT, - ( UBaseType_t ) ETH_TX_DESC_CNT, - &xTxDescSemBuf - ); - #else - xTxDescSem = xSemaphoreCreateCounting( - ( UBaseType_t ) ETH_TX_DESC_CNT, - ( UBaseType_t ) ETH_TX_DESC_CNT - ); - #endif - configASSERT( xTxDescSem != NULL ); - if( xTxDescSem == NULL ) - { - break; - } - vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); - } - - if( xEMACTaskHandle == NULL ) - { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) - static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; - static StaticTask_t xEMACTaskTCB; - xEMACTaskHandle = xTaskCreateStatic( - prvEMACHandlerTask, - niEMAC_TASK_NAME, - niEMAC_TASK_STACK_SIZE, - ( void * ) &xEthHandle, - niEMAC_TASK_PRIORITY, - uxEMACTaskStack, - &xEMACTaskTCB - ); - #else - xResult = xTaskCreate( - prvEMACHandlerTask, - niEMAC_TASK_NAME, - niEMAC_TASK_STACK_SIZE, - ( void * ) &xEthHandle, - niEMAC_TASK_PRIORITY, - &xEMACTaskHandle - ); - configASSERT( xResult == pdPASS ); - #endif - configASSERT( xEMACTaskHandle != NULL ); - if( xEMACTaskHandle == NULL ) - { - break; - } + break; } xMacInitStatus = eMacEthStart; /* fallthrough */ case eMacEthStart: - if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) + if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) { - xHalResult = HAL_ETH_Start_IT( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); - if( xHalResult != HAL_OK ) + if( HAL_ETH_Start_IT( pxEthHandle ) != HAL_OK ) { break; } } - configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); - configASSERT( xEthHandle.RxDescList.ItMode == 1U ); xMacInitStatus = eMacInitComplete; /* fallthrough */ case eMacInitComplete: - configASSERT( xEthHandle.gState != HAL_ETH_STATE_ERROR ); if( prvGetPhyLinkStatus( pxInterface ) == pdTRUE ) { xInitResult = pdPASS; @@ -612,110 +342,109 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac return xInitResult; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; - configASSERT( pxDescriptor != NULL ); /* Zero-Copy Only */ - configASSERT( xReleaseAfterSend != pdFALSE ); - iptraceNETWORK_INTERFACE_OUTPUT( pxDescriptor->xDataLength, pxDescriptor->pucEthernetBuffer ); + configASSERT( xReleaseAfterSend == pdTRUE ); - if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ) ) + if( ( xMacInitStatus == eMacInitComplete ) && ( xEthHandle.gState == HAL_ETH_STATE_STARTED ) ) { - if( prvGetPhyLinkStatus( pxInterface ) != pdFAIL ) + if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ) ) { - static ETH_TxPacketConfig xTxConfig = { - .CRCPadCtrl = ETH_CRC_PAD_INSERT, - #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, - .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, - #else - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, - .ChecksumCtrl = ETH_CHECKSUM_DISABLE, - #endif - }; - - ETH_BufferTypeDef xTxBuffer = { - .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, - .len = pxDescriptor->xDataLength, - .next = NULL - }; - configASSERT( xTxBuffer.len <= ETH_MAX_PACKET_SIZE ); - - xTxConfig.Length = xTxBuffer.len; - xTxConfig.TxBuffer = &xTxBuffer; - xTxConfig.pData = pxDescriptor; - - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) != pdFALSE ) + if( prvGetPhyLinkStatus( pxInterface ) != pdFAIL ) { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 50U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) != pdFALSE ) { - HAL_StatusTypeDef xHalResult = HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ); - xSemaphoreGive( xTxMutex ); - if( xHalResult == HAL_OK ) - { - /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ - xReleaseAfterSend = pdFALSE; - xResult = pdPASS; - } - else + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) { - ( void ) xSemaphoreGive( xTxDescSem ); - configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); - if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) + static ETH_TxPacketConfig xTxConfig = { + .CRCPadCtrl = ETH_CRC_PAD_INSERT, + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, + .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, + #else + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, + .ChecksumCtrl = ETH_CHECKSUM_DISABLE, + #endif + }; + + ETH_BufferTypeDef xTxBuffer = { + .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + + xTxConfig.Length = xTxBuffer.len; + xTxConfig.TxBuffer = &xTxBuffer; + xTxConfig.pData = pxDescriptor; + if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Eth Not Started\n" ) ); + /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ + xReleaseAfterSend = pdFALSE; + xResult = pdPASS; } - if( xEthHandle.ErrorCode & HAL_ETH_ERROR_BUSY ) + else { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); - xHalResult = HAL_ETH_ReleaseTxPacket( &xEthHandle ); - configASSERT( xHalResult == HAL_OK ); + ( void ) xSemaphoreGive( xTxDescSem ); + configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); + if( xEthHandle.ErrorCode & HAL_ETH_ERROR_BUSY ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); + } } + ( void ) xSemaphoreGive( xTxMutex ); + } + else + { + ( void ) xSemaphoreGive( xTxDescSem ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); } } else { - xSemaphoreGive( xTxDescSem ); - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); } } else { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); } } else { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Descriptor\n" ) ); } } else { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Buffer\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Eth Not Started\n" ) ); } - if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend != pdFALSE ) ) + if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend == pdTRUE ) && ( xResult == pdFAIL ) ) { vReleaseNetworkBufferAndDescriptor( pxDescriptor ); } - /*if( xResult == pdFAIL ) + if( xResult == pdFAIL ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Failed\n" ) ); - xTaskNotify( xEMACTaskHandle, eMacEventErrTx, eSetBits ); - }*/ + } return xResult; } -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* EMAC Task */ +/*===========================================================================*/ -static UBaseType_t prvNetworkInterfaceInput( void ) +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) { - UBaseType_t xResult = 0; + UBaseType_t uxResult = 0; + /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; NetworkBufferDescriptor_t * pxEndDescriptor = NULL; @@ -724,32 +453,31 @@ static UBaseType_t prvNetworkInterfaceInput( void ) IPStackEvent_t xRxEvent; xRxEvent.eEventType = eNetworkRxEvent; - while ( ( HAL_ETH_ReadData( &xEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) ) + while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { - /* configASSERT( xEthHandle.RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); */ if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ continue; } - iptraceNETWORK_INTERFACE_INPUT( pxCurDescriptor->xDataLength, pxCurDescriptor->pucEthernetBuffer ); - ++xResult; + configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); + ++uxResult; pxCurDescriptor->pxInterface = pxMyInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); /* TODO: check pxEndPoint exists? Check it earlier before getting buffer? */ #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - if ( pxStartDescriptor == NULL ) + if( pxStartDescriptor == NULL ) { pxStartDescriptor = pxCurDescriptor; } - else if ( pxEndDescriptor != NULL ) + else if( pxEndDescriptor != NULL ) { pxEndDescriptor->pxNextBuffer = pxCurDescriptor; } pxEndDescriptor = pxCurDescriptor; #else xRxEvent.pvData = ( void * ) pxCurDescriptor; - if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 20U ) != pdPASS ) + if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); @@ -759,10 +487,10 @@ static UBaseType_t prvNetworkInterfaceInput( void ) } #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - if( xResult > 0 ) + if( uxResult > 0 ) { xRxEvent.pvData = ( void * ) pxStartDescriptor; - if( xSendEventStructToIPTask( &xRxEvent, niEMAC_MAX_BLOCK_TIME_MS ) != pdPASS ) + if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); @@ -776,56 +504,63 @@ static UBaseType_t prvNetworkInterfaceInput( void ) } #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ - if( xResult == 0 ) + if( uxResult == 0 ) { - ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); - } + configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + /* ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); */ - configASSERT( xEthHandle.ErrorCode != HAL_ETH_ERROR_PARAM ); - if( xEthHandle.gState != HAL_ETH_STATE_STARTED ) - { - ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); + if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) + { + ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); + } } - return ( ( BaseType_t ) ( xResult > 0 ) ); + return ( ( BaseType_t ) ( uxResult > 0 ) ); } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { ETH_HandleTypeDef * pxEthHandle = ( ETH_HandleTypeDef * ) pvParameters; configASSERT( pxEthHandle ); + /* iptraceEMAC_TASK_STARTING(); */ + for( ;; ) { - BaseType_t xResult = 0U; + BaseType_t xResult = pdFALSE; uint32_t ulISREvents = 0U; - if ( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdTRUE ) + if( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdTRUE ) { - HAL_StatusTypeDef xHalResult; - if( ( ulISREvents & eMacEventRx ) != 0 ) { - xResult = ( prvNetworkInterfaceInput() > 0 ); + xResult = prvNetworkInterfaceInput( pxEthHandle ); } if( ( ulISREvents & eMacEventTx ) != 0 ) { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) { - xHalResult = HAL_ETH_ReleaseTxPacket( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); + ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); ( void ) xSemaphoreGive( xTxMutex ); } } + + if( ( ulISREvents & eMacEventErrRx ) != 0 ) + { + /*do { + xResult = ( prvNetworkInterfaceInput() > 0 ); + } while ( xResult != pdFALSE ); + xResult = pdTRUE;*/ + } + if( ( ulISREvents & eMacEventErrTx ) != 0 ) { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 1000U ) ) != pdFALSE ) + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) { - xHalResult = HAL_ETH_ReleaseTxPacket( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); + ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > pxEthHandle->TxDescList.BuffersInUse ) { ( void ) xSemaphoreGive( xTxDescSem ); @@ -833,211 +568,520 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } } - if( ( ulISREvents & eMacEventErrRx ) != 0 ) - { - /*do { - xResult = ( prvNetworkInterfaceInput() > 0 ); - } while ( xResult != pdFALSE ); - xResult = pdTRUE;*/ - } - if( ( ulISREvents & eMacEventErrEth ) != 0 ) { - /* pxEthHandle->gState */ - /* pxEthHandle->ErrorCode */ + configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + pxEthHandle->gState = HAL_ETH_STATE_STARTED; + ( void ) HAL_ETH_Stop_IT( pxEthHandle ); + ( void ) HAL_ETH_DeInit( pxEthHandle ); + if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) + { + ( void ) HAL_ETH_Start_IT( pxEthHandle ); + } } if( ( ulISREvents & eMacEventErrMac ) != 0 ) { + /* pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC */ /* pxEthHandle->MACErrorCode */ } if( ( ulISREvents & eMacEventErrDma ) != 0 ) { - /* TODO: Does this recover from fatal bus error? */ - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( 5000U ) ) != pdFALSE ) - { - /* pxEthHandle->DMAErrorCode */ - pxEthHandle->gState = HAL_ETH_STATE_STARTED; - xHalResult = HAL_ETH_Stop_IT( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_READY ); - configASSERT( pxEthHandle->RxDescList.ItMode == 0U); - xHalResult = HAL_ETH_DeInit( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_RESET ); - xHalResult = HAL_ETH_Init( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); - configASSERT( pxEthHandle->ErrorCode == HAL_ETH_ERROR_NONE ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_READY ); - xHalResult = HAL_ETH_Start_IT( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); - configASSERT( pxEthHandle->RxDescList.ItMode == 1U); - xSemaphoreGive( xTxMutex ); - } + /* pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA */ + /* pxEthHandle->DMAErrorCode */ } - - (void) xHalResult; } if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { - prvEthernetUpdateConfig( pxEthHandle ); + if( prvGetPhyLinkStatus( pxMyInterface ) != pdFALSE ) + { + if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + { + ( void ) HAL_ETH_Start_IT( pxEthHandle ); + } + } + else + { + ( void ) HAL_ETH_Stop_IT( pxEthHandle ); + #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) + ( void ) HAL_ETH_DeInit( pxEthHandle ); + xMacInitStatus = eMacEthInit; + FreeRTOS_NetworkDown( pxMyInterface ); + #endif + } } } } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor ) +static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) { BaseType_t xResult = pdFALSE; - uint32_t pErrorCode = 0; - const HAL_StatusTypeDef xHalResult = HAL_ETH_GetRxDataErrorCode( &xEthHandle, &pErrorCode ); - configASSERT( xHalResult == HAL_OK ); - (void) xHalResult; + if( xTxMutex == NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + static StaticSemaphore_t xTxMutexBuf; + xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); + #else + xTxMutex = xSemaphoreCreateMutex(); + #endif + configASSERT( xTxMutex != NULL ); + vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); + } - /* Fxx - ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT | ETH_DMARXDESC_LC | ETH_DMARXDESC_CE | ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE */ - /* Hxx - ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT | ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE */ + if( xTxDescSem == NULL ) + { + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT, + &xTxDescSemBuf + ); + #else + xTxDescSem = xSemaphoreCreateCounting( + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT + ); + #endif + configASSERT( xTxDescSem != NULL ); + vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); + } - if ( pErrorCode == 0 ) + if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) { - /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS, ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES */ - /* ETH_IP_PAYLOAD_UNKNOWN */ - const eFrameProcessingResult_t xFrameProcessingResult = niEMAC_CONSIDER_FRAME_FOR_PROCESSING( pxDescriptor->pucEthernetBuffer ); - if( xFrameProcessingResult == eProcessBuffer ) + #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; + static StaticTask_t xEMACTaskTCB; + xEMACTaskHandle = xTaskCreateStatic( + prvEMACHandlerTask, + niEMAC_TASK_NAME, + niEMAC_TASK_STACK_SIZE, + ( void * ) pxEthHandle, + niEMAC_TASK_PRIORITY, + uxEMACTaskStack, + &xEMACTaskTCB + ); + #else + ( void ) xTaskCreate( + prvEMACHandlerTask, + niEMAC_TASK_NAME, + niEMAC_TASK_STACK_SIZE, + ( void * ) pxEthHandle, + niEMAC_TASK_PRIORITY, + &xEMACTaskHandle + ); + #endif + } + + if( xEMACTaskHandle != NULL ) + { + xResult = pdTRUE; + } + + return xResult; +} + +/*===========================================================================*/ +/* EMAC Init */ +/*===========================================================================*/ + +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ) +{ + BaseType_t xResult = pdFALSE; + + pxEthHandle->Instance = ETH; + + #if ( niEMAC_USE_RMII != 0 ) + pxEthHandle->Init.MediaInterface = HAL_ETH_RMII_MODE; + #else + pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE; + #endif + + pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; + configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); + configASSERT( pxEthHandle->Init.RxBuffLen % 4U == 0 ); + + static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); + static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); + + pxEthHandle->Init.TxDesc = xDMADescTx; + pxEthHandle->Init.RxDesc = xDMADescRx; + + ( void ) memset( &xDMADescTx, 0, sizeof( xDMADescTx ) ); + ( void ) memset( &xDMADescRx, 0, sizeof( xDMADescRx ) ); + + const NetworkEndPoint_t * const pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + if( pxEndPoint != NULL ) + { + pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; + + #if defined( STM32F7 ) || defined( STM32F4 ) + /* This function doesn't get called in Fxx driver */ + HAL_ETH_SetMDIOClockRange( pxEthHandle ); + #endif + + if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) { xResult = pdTRUE; } - else + /* else { - /* Other Enum Values Are Invalid */ - configASSERT( xFrameProcessingResult == eReleaseBuffer ); - } + pxEthHandle->ErrorCode & HAL_ETH_ERROR_TIMEOUT + } */ } return xResult; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) +static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - BaseType_t xResult = pdTRUE; + /* #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + #endif */ + + #if ( ipconfigUSE_MDNS != 0 ) + prvMACAddressConfig( pxEthHandle, xMDNS_MacAddress.ucBytes ); + #if ( ipconfigUSE_IPv6 != 0 ) + prvMACAddressConfig( pxEthHandle, xMDNS_MACAddressIPv6.ucBytes ); + #endif + #endif - if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + #if ( ipconfigUSE_LLMNR != 0 ) + prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddress.ucBytes ); + #if ( ipconfigUSE_IPv6 != 0 ) + prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddressIPv6.ucBytes ); + #endif + #endif + + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - xResult = pdFALSE; + #if ( ipconfigUSE_IPv6 != 0 ) + if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) + { + const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { + 0x33, + 0x33, + 0xff, + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], + pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] + }; + prvMACAddressConfig( pxEthHandle, ucMACAddress ); + } + #else + if( pxEthHandle->Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) + { + prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); + } + #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + } + + #if ( ipconfigUSE_IPv6 != 0 ) + prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + #endif + + /* #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + #endif */ +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +{ + BaseType_t xResult = pdFALSE; + + if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) + { + const PhyProperties_t xPhyProperties = { + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + .ucSpeed = PHY_SPEED_AUTO, + .ucDuplex = PHY_DUPLEX_AUTO, + #else + .ucSpeed = ( niEMAC_USE_100MB != 0 ) ? PHY_SPEED_100 : PHY_SPEED_10, + .ucDuplex = ( niEMAC_USE_FULL_DUPLEX != 0 ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF, + #endif + + #if ( niEMAC_AUTO_CROSS != 0 ) + .ucMDI_X = PHY_MDIX_AUTO, + #elif ( niEMAC_CROSSED_LINK != 0 ) + .ucMDI_X = PHY_MDIX_CROSSED, + #else + .ucMDI_X = PHY_MDIX_DIRECT, + #endif + }; + + if( xPhyConfigure( &xPhyObject, &xPhyProperties ) == 0 ) + { + if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + { + xResult = pdTRUE; + } + } + } + else + { + xResult = pdTRUE; } return xResult; } -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* MAC Helpers */ +/*===========================================================================*/ -static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) { - BaseType_t xResult = pdTRUE; + BaseType_t xResult = pdFALSE; - if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) + if( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) { - xResult = pdFALSE; + ( void ) HAL_ETH_Stop_IT( pxEthHandle ); + } + + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + xMACConfig.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); + + #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ + ( void ) xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + #else + xPhyObject.xPhyPreferences.ucSpeed = ( niEMAC_USE_100MB != 0 ) ? PHY_SPEED_100 : PHY_SPEED_10; + xPhyObject.xPhyPreferences.ucDuplex = ( niEMAC_USE_FULL_DUPLEX != 0 ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + /* ucMDI_X unused */ + /* TODO: xPhyFixedValue always return 0 */ + ( void ) xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + xMACConfig.DuplexMode = xPhyObject.xPhyPreferences.ucDuplex; + xMACConfig.Speed = xPhyObject.xPhyPreferences.ucSpeed; + #endif + + if( HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ) == HAL_OK ) + { + xResult = pdTRUE; } return xResult; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -static void prvEthernetUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) +/* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ +static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ) { - BaseType_t xResult; - HAL_StatusTypeDef xHalResult; + uint32_t ulCRC32 = 0xFFFFFFFF; - if( prvGetPhyLinkStatus( pxMyInterface ) != pdFALSE ) + for( UBaseType_t i = 0; i < 6; ++i ) { - if(HAL_ETH_GetState(pxEthHandle) == HAL_ETH_STATE_STARTED) { - xHalResult = HAL_ETH_Stop_IT(pxEthHandle); - configASSERT(xHalResult == HAL_OK); + ulCRC32 ^= ( uint32_t ) pucMAC[ i ]; + + for( UBaseType_t j = 0; j < 8; ++j ) + { + ulCRC32 >>= 1; + if( ulCRC32 & 1 ) + { + /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ + ulCRC32 ^= __RBIT( 0x04C11DB7 ); + } } + } - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) - /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ - xResult = xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - #else - /* Use predefined (fixed) configuration. */ - xResult = xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - #endif - configASSERT( xResult == 0 ); + ulCRC32 = ~( ulCRC32 ); + return ulCRC32; +} - ETH_MACConfigTypeDef xMACConfig; - xHalResult = HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - configASSERT( xHalResult == HAL_OK ); +/*---------------------------------------------------------------------------*/ - xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; +/* Compute the hash value of a given MAC address to index the bits in the Hash Table */ +static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ) +{ + /* Calculate the 32-bit CRC for the MAC */ + const uint32_t ulCRC32 = prvComputeCRC32_MAC( pucMAC ); + + /* Perform bitwise reversal on the CRC32 */ + const uint32_t ulHash = __RBIT( ulCRC32 ); + + /* Take the upper 6 bits of the above result */ + return ( ulHash >> 26 ); +} - xHalResult = HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ); - configASSERT( xHalResult == HAL_OK ); +/*---------------------------------------------------------------------------*/ - xHalResult = HAL_ETH_Start_IT( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); +/* Update the Hash Table Registers with hash value of the given MAC address */ +static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) +{ + static uint32_t ulHashTable[ 2 ]; + + const uint32_t ulHash = prvComputeEthernet_MACHash( pucMAC ); + + /* Use the upper or lower Hash Table Registers + * to set the required bit based on the ulHash */ + if( ulHash < 32 ) + { + ulHashTable[ 0 ] = ulHash; } else { - /* iptraceNETWORK_INTERFACE_STATUS_CHANGE(); */ - xHalResult = HAL_ETH_Stop_IT( pxEthHandle ); - configASSERT( xHalResult == HAL_OK ); - - #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) - FreeRTOS_NetworkDown( pxMyInterface ); - #endif + ulHashTable[ 1 ] = ulHash; } - (void) xHalResult; - (void) xResult; + ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, const uint8_t * addr ) +static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucAddr ) { /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - static UBaseType_t xMACEntry = ETH_MAC_ADDRESS1; + static UBaseType_t uxMACEntry = ETH_MAC_ADDRESS1; - switch(xMACEntry) + switch( uxMACEntry ) { case ETH_MAC_ADDRESS1: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS1, ( uint8_t* ) addr ); - prvSetMAC_HashFilter( pxEthHandle, addr ); - xMACEntry = ETH_MAC_ADDRESS2; + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); + uxMACEntry = ETH_MAC_ADDRESS2; break; case ETH_MAC_ADDRESS2: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS2, ( uint8_t* ) addr ); - prvSetMAC_HashFilter( pxEthHandle, addr ); - xMACEntry = ETH_MAC_ADDRESS3; + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); + uxMACEntry = ETH_MAC_ADDRESS3; break; case ETH_MAC_ADDRESS3: - HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, ETH_MAC_ADDRESS3, ( uint8_t* ) addr ); - prvSetMAC_HashFilter( pxEthHandle, addr ); - xMACEntry = ETH_MAC_ADDRESS0; + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); + uxMACEntry = ETH_MAC_ADDRESS0; break; case ETH_MAC_ADDRESS0: - /* fallthrough */ + prvSetMAC_HashFilter( pxEthHandle, pucAddr ); + break; default: break; } } -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Rx Helpers */ +/*===========================================================================*/ + +#if 0 +#if ( defined( STM32F4 ) || defined( STM32F7 ) ) + #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR + #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR + + #define ETH_IP_PAYLOAD_UNKNOWN 0x00000000U + #define ETH_IP_PAYLOAD_UDP ETH_DMAPTPRXDESC_IPPT_UDP + #define ETH_IP_PAYLOAD_TCP ETH_DMAPTPRXDESC_IPPT_TCP + #define ETH_IP_PAYLOAD_ICMPN ETH_DMAPTPRXDESC_IPPT_ICMP +#endif + +static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ) +{ + BaseType_t xResult = pdFALSE; + + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) + const UBaseType_t uxPayloadType = READ_BIT( heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_PT ) + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + switch( uxPayloadType ) + { + case ETH_IP_PAYLOAD_UNKNOWN: + case ETH_IP_PAYLOAD_UDP: + if( ( xPortHasUdpSocket( xUDPHeader->usDestinationPort ) ) + #if( ipconfigUSE_DNS == 1 ) * DNS is also UDP. * + || ( xUDPHeader->usSourcePort == FreeRTOS_ntohs( ipDNS_PORT ) ) + #endif + #if( ipconfigUSE_LLMNR == 1 ) * LLMNR is also UDP. * + || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) + #endif + #if( ipconfigUSE_NBNS == 1 ) * NBNS is also UDP. * + || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) + #endif + ) + { + xResult = pdTRUE; + } + else + { + xResult = pdFALSE; + } + break; + + case ETH_IP_PAYLOAD_TCP: + case ETH_IP_PAYLOAD_ICMPN: + default: + } + #endif + + return xResult; +} +#endif + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ) +{ + BaseType_t xResult = pdFALSE; -static BaseType_t xSwitchRequired; + uint32_t ulErrorCode = 0; + ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); + + if ( ulErrorCode == 0 ) + { + if( usLength <= niEMAC_DATA_BUFFER_SIZE ) + { + /* if( prvAcceptPayload( &xEthHandle, pxDescriptor->pucEthernetBuffer ) != pdFALSE ) + { + + } + else + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Payload discarded\n" ) ); + } + */ + + #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + xResult = pdTRUE; + #else + /* TODO: Handle this in hardware via HAL_ETH_SetMACFilterConfig */ + if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) == eProcessBuffer ) + { + xResult = pdTRUE; + } + else + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); + } + #endif + } + else + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); + } + } + else + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); + } + + return xResult; +} + +/*===========================================================================*/ +/* IRQ Handlers */ +/*===========================================================================*/ void ETH_IRQHandler( void ) { @@ -1049,9 +1093,9 @@ void ETH_IRQHandler( void ) portYIELD_FROM_ISR( xSwitchRequired ); } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *pxEthHandle ) +void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA ) @@ -1061,23 +1105,30 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *pxEthHandle ) if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Fatal bus error occurred */ - /* Fxx - ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS */ - /* Hxx - ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS */ - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrDma, eSetBits, &xHigherPriorityTaskWoken ); + /* eMacEventErrDma */ + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrEth, eSetBits, &xHigherPriorityTaskWoken ); } else { - /* Fxx - ETH_DMASR_ETS | ETH_DMASR_RWTS | ETH_DMASR_RBUS | ETH_DMASR_AIS */ - /* Hxx - ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | ETH_DMACSR_RBU | ETH_DMACSR_AIS */ #if defined( STM32F4 ) || defined ( STM32F7 ) - if( ( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) == ETH_DMASR_TBUS) + if( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) { ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); } - if( ( pxEthHandle->DMAErrorCode & ETH_DMASR_RBUS ) == ETH_DMASR_RBUS) + if( pxEthHandle->DMAErrorCode & ETH_DMASR_RBUS ) { - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); */ + } + #elif defined( STM32H5 ) || defined ( STM32H7 ) + if( pxEthHandle->DMAErrorCode & ETH_DMACSR_TBU ) + { + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); + } + + if( pxEthHandle->DMAErrorCode & ETH_DMACSR_RBU ) + { + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); */ } #endif } @@ -1088,14 +1139,16 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef *pxEthHandle ) { if( pxEthHandle->MACErrorCode ) { - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); */ } } + configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + xSwitchRequired |= xHigherPriorityTaskWoken; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) { @@ -1115,14 +1168,36 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) xSwitchRequired |= xHigherPriorityTaskWoken; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) +{ + static size_t uxMostTXDescsUsed = 0U; + + const size_t uxTxUsed = pxEthHandle->TxDescList.BuffersInUse; + + if( uxMostTXDescsUsed < uxTxUsed ) + { + uxMostTXDescsUsed = uxTxUsed; + } + + iptraceNETWORK_INTERFACE_TRANSMIT(); + + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; +} + +/*===========================================================================*/ +/* HAL Tx/Rx Callbacks */ +/*===========================================================================*/ -void HAL_ETH_RxAllocateCallback( uint8_t **buff ) +void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) { const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { - *buff = pxBufferDescriptor->pucEthernetBuffer; + *ppucBuff = pxBufferDescriptor->pucEthernetBuffer; } else { @@ -1130,16 +1205,16 @@ void HAL_ETH_RxAllocateCallback( uint8_t **buff ) } } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t Length ) +void HAL_ETH_RxLinkCallback( void ** pStart, void ** pEnd, uint8_t * buff, uint16_t usLength ) { NetworkBufferDescriptor_t ** const pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; NetworkBufferDescriptor_t ** const pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); - if ( Length <= niEMAC_DATA_BUFFER_SIZE && prvAcceptPacket( pxCurDescriptor ) == pdTRUE ) + if( prvAcceptPacket( pxCurDescriptor, usLength ) == pdTRUE ) { - pxCurDescriptor->xDataLength = Length; + pxCurDescriptor->xDataLength = usLength; #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) pxCurDescriptor->pxNextBuffer = NULL; #endif @@ -1173,33 +1248,55 @@ void HAL_ETH_RxLinkCallback( void **pStart, void **pEnd, uint8_t *buff, uint16_t } } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ -void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) +void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) { - static size_t uxMostTXDescsUsed = 0U; + NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) pulBuff; + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + ( void ) xSemaphoreGive( xTxDescSem ); +} - const size_t uxTxUsed = pxEthHandle->TxDescList.BuffersInUse; +/*===========================================================================*/ +/* Buffer Allocation */ +/*===========================================================================*/ - if( uxMostTXDescsUsed < uxTxUsed ) - { - uxMostTXDescsUsed = uxTxUsed; - } +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_CACHE_LINE_SIZE ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); - iptraceNETWORK_INTERFACE_TRANSMIT(); + configASSERT( xBufferAllocFixedSize == pdTRUE ); - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); - xSwitchRequired |= xHigherPriorityTaskWoken; + for( size_t uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++uxIndex ) + { + pxNetworkBuffers[ uxIndex ].pucEthernetBuffer = &( ucNetworkPackets[ uxIndex ][ ipBUFFER_PADDING ] ); + *( ( uint32_t * ) &( ucNetworkPackets[ uxIndex ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ uxIndex ] ) ); + } } -/*-----------------------------------------------------------*/ +/*===========================================================================*/ +/* Network Interface Definition */ +/*===========================================================================*/ -void HAL_ETH_TxFreeCallback( uint32_t *buff ) +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { - NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) buff; - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - ( void ) xSemaphoreGive( xTxDescSem ); + static char pcName[ 17 ]; + + ( void ) snprintf( pcName, sizeof( pcName ), "eth%u", ( unsigned ) xEMACIndex ); + + ( void ) memset( pxInterface, '\0', sizeof( *pxInterface ) ); + pxInterface->pcName = pcName; + /* TODO: use pvArgument to get xPhyObject/xEthHandle/xMacInitStatus? */ + pxInterface->pvArgument = ( void * ) xEMACIndex; + pxInterface->pfInitialise = prvNetworkInterfaceInitialise; + pxInterface->pfOutput = prvNetworkInterfaceOutput; + pxInterface->pfGetPhyLinkStatus = prvGetPhyLinkStatus; + /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; + pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ + + pxMyInterface = FreeRTOS_AddNetworkInterface( pxInterface ); + + return pxMyInterface; } -/*-----------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ From 4319b6f7979b67ae3488c944adb97290e01f7a85 Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 5 Jan 2024 19:33:22 -0500 Subject: [PATCH 30/68] reconnection fixes --- .../NetworkInterface/STM32/NetworkInterface.c | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 5e64f527ff..91acd8414a 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -571,13 +571,6 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrEth ) != 0 ) { configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - pxEthHandle->gState = HAL_ETH_STATE_STARTED; - ( void ) HAL_ETH_Stop_IT( pxEthHandle ); - ( void ) HAL_ETH_DeInit( pxEthHandle ); - if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) - { - ( void ) HAL_ETH_Start_IT( pxEthHandle ); - } } if( ( ulISREvents & eMacEventErrMac ) != 0 ) @@ -593,21 +586,27 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } } + /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ + if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) { if( prvGetPhyLinkStatus( pxMyInterface ) != pdFALSE ) { - if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + if( pxEthHandle->gState == HAL_ETH_STATE_READY ) { - ( void ) HAL_ETH_Start_IT( pxEthHandle ); + /* Link Was Down */ + if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + { + ( void ) HAL_ETH_Start_IT( pxEthHandle ); + } } } else { ( void ) HAL_ETH_Stop_IT( pxEthHandle ); #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) - ( void ) HAL_ETH_DeInit( pxEthHandle ); - xMacInitStatus = eMacEthInit; + /* ( void ) HAL_ETH_DeInit( pxEthHandle ); + xMacInitStatus = eMacEthInit; */ FreeRTOS_NetworkDown( pxMyInterface ); #endif } From 2bd8eb4b1adc1bf0de3162cbd5635ff39d272883 Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 6 Jan 2024 01:01:45 -0500 Subject: [PATCH 31/68] fix pcLOCAL_ALL_NODES_MULTICAST_MAC issue --- source/FreeRTOS_ND.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index ab30a6f769..6dbc866b2a 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -1179,7 +1179,7 @@ pxICMPPacket = ( ( ICMPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( pxICMPPacket->xICMPHeaderIPv6 ) ); - ( void ) memcpy( pxICMPPacket->xEthernetHeader.xDestinationAddress.ucBytes, pcLOCAL_ALL_NODES_MULTICAST_MAC, ipMAC_ADDRESS_LENGTH_BYTES ); + ( void ) memcpy( pxICMPPacket->xEthernetHeader.xDestinationAddress.ucBytes, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ); ( void ) memcpy( pxICMPPacket->xEthernetHeader.xSourceAddress.ucBytes, pxEndPoint->xMACAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ); pxICMPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE; /* 12 + 2 = 14 */ From e8fe63ad2badd0093c8694516416550d07dca5ea Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 6 Jan 2024 04:04:19 -0500 Subject: [PATCH 32/68] config checks cleanup --- .../NetworkInterface/STM32/NetworkInterface.c | 88 +++++++++---------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 91acd8414a..db96974717 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -67,19 +67,19 @@ /* Config Checks */ /*===========================================================================*/ -#if ( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) - #if ( ipconfigPORT_SUPPRESS_WARNING == 0 ) +#if ( ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) + #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) #warning Consider enabling checksum offloading for NetworkInterface #endif #endif #if ( ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) ) - #if ( ipconfigPORT_SUPPRESS_WARNING == 0 ) + #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) #warning Unsupported ipconfigNETWORK_MTU size #endif #endif -#if ( configUSE_TASK_NOTIFICATIONS == 0 ) +#if ( ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) ) #error Task Notifications must be enabled for NetworkInterface #endif @@ -122,13 +122,13 @@ /* #define niEMAC_PHY_COUNT 1 */ -#define niEMAC_AUTO_NEGOTIATION 1 -#define niEMAC_USE_100MB ( 1 && ( niEMAC_AUTO_NEGOTIATION == 0 ) ) -#define niEMAC_USE_FULL_DUPLEX ( 1 && ( niEMAC_AUTO_NEGOTIATION == 0 ) ) -#define niEMAC_AUTO_CROSS ( 1 && ( niEMAC_AUTO_NEGOTIATION != 0 ) ) -#define niEMAC_CROSSED_LINK ( 1 && ( niEMAC_AUTO_CROSS == 0 ) ) +#define niEMAC_AUTO_NEGOTIATION ipconfigENABLE +#define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) -#define niEMAC_USE_RMII 1 +#define niEMAC_USE_RMII ipconfigENABLE /*===========================================================================*/ /* Enums */ @@ -362,7 +362,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N { static ETH_TxPacketConfig xTxConfig = { .CRCPadCtrl = ETH_CRC_PAD_INSERT, - #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ) .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, #else @@ -445,7 +445,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) { UBaseType_t uxResult = 0; /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif @@ -465,7 +465,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) pxCurDescriptor->pxInterface = pxMyInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); /* TODO: check pxEndPoint exists? Check it earlier before getting buffer? */ - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) if( pxStartDescriptor == NULL ) { pxStartDescriptor = pxCurDescriptor; @@ -483,10 +483,10 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); } - #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ + #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) */ } - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) if( uxResult > 0 ) { xRxEvent.pvData = ( void * ) pxStartDescriptor; @@ -502,7 +502,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) } while( pxDescriptorToClear != NULL ); } } - #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ + #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) */ if( uxResult == 0 ) { @@ -604,7 +604,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) else { ( void ) HAL_ETH_Stop_IT( pxEthHandle ); - #if ( ipconfigSUPPORT_NETWORK_DOWN_EVENT != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_NETWORK_DOWN_EVENT ) ) /* ( void ) HAL_ETH_DeInit( pxEthHandle ); xMacInitStatus = eMacEthInit; */ FreeRTOS_NetworkDown( pxMyInterface ); @@ -622,7 +622,7 @@ static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) if( xTxMutex == NULL ) { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) static StaticSemaphore_t xTxMutexBuf; xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); #else @@ -634,7 +634,7 @@ static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) if( xTxDescSem == NULL ) { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) static StaticSemaphore_t xTxDescSemBuf; xTxDescSem = xSemaphoreCreateCountingStatic( ( UBaseType_t ) ETH_TX_DESC_CNT, @@ -653,7 +653,7 @@ static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) { - #if ( configSUPPORT_STATIC_ALLOCATION != 0 ) + #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; static StaticTask_t xEMACTaskTCB; xEMACTaskHandle = xTaskCreateStatic( @@ -695,7 +695,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo pxEthHandle->Instance = ETH; - #if ( niEMAC_USE_RMII != 0 ) + #if ( ipconfigIS_ENABLED( niEMAC_USE_RMII ) ) pxEthHandle->Init.MediaInterface = HAL_ETH_RMII_MODE; #else pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE; @@ -741,28 +741,28 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - /* #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + /* #if ( ipconfigIS_ENABLEDipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) ETH_MACFilterConfigTypeDef xFilterConfig; ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); #endif */ - #if ( ipconfigUSE_MDNS != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) ) prvMACAddressConfig( pxEthHandle, xMDNS_MacAddress.ucBytes ); - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, xMDNS_MACAddressIPv6.ucBytes ); #endif #endif - #if ( ipconfigUSE_LLMNR != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddress.ucBytes ); - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddressIPv6.ucBytes ); #endif #endif for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) { const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { @@ -780,14 +780,14 @@ static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa { prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); } - #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ + #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ } - #if ( ipconfigUSE_IPv6 != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); #endif - /* #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES != 0 ) + /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); #endif */ } @@ -801,17 +801,17 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { const PhyProperties_t xPhyProperties = { - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + #if ( ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) .ucSpeed = PHY_SPEED_AUTO, .ucDuplex = PHY_DUPLEX_AUTO, #else - .ucSpeed = ( niEMAC_USE_100MB != 0 ) ? PHY_SPEED_100 : PHY_SPEED_10, - .ucDuplex = ( niEMAC_USE_FULL_DUPLEX != 0 ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF, + .ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10, + .ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF, #endif - #if ( niEMAC_AUTO_CROSS != 0 ) + #if ( ipconfigIS_ENABLED( niEMAC_AUTO_CROSS ) ) .ucMDI_X = PHY_MDIX_AUTO, - #elif ( niEMAC_CROSSED_LINK != 0 ) + #elif ( ipconfigIS_ENABLED( niEMAC_CROSSED_LINK ) ) .ucMDI_X = PHY_MDIX_CROSSED, #else .ucMDI_X = PHY_MDIX_DIRECT, @@ -849,16 +849,16 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) ETH_MACConfigTypeDef xMACConfig; ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - xMACConfig.ChecksumOffload = ( FunctionalState ) ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ); + xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); - #if ( niEMAC_AUTO_NEGOTIATION != 0 ) + #if ( ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ ( void ) xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; #else - xPhyObject.xPhyPreferences.ucSpeed = ( niEMAC_USE_100MB != 0 ) ? PHY_SPEED_100 : PHY_SPEED_10; - xPhyObject.xPhyPreferences.ucDuplex = ( niEMAC_USE_FULL_DUPLEX != 0 ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + xPhyObject.xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; + xPhyObject.xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; /* ucMDI_X unused */ /* TODO: xPhyFixedValue always return 0 */ ( void ) xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); @@ -990,7 +990,7 @@ static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8 { BaseType_t xResult = pdFALSE; - #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) const UBaseType_t uxPayloadType = READ_BIT( heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_PT ) const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); @@ -1051,7 +1051,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes } */ - #if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + #if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) xResult = pdTRUE; #else /* TODO: Handle this in hardware via HAL_ETH_SetMACFilterConfig */ @@ -1214,14 +1214,14 @@ void HAL_ETH_RxLinkCallback( void ** pStart, void ** pEnd, uint8_t * buff, uint1 if( prvAcceptPacket( pxCurDescriptor, usLength ) == pdTRUE ) { pxCurDescriptor->xDataLength = usLength; - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) pxCurDescriptor->pxNextBuffer = NULL; #endif if( *pStartDescriptor == NULL ) { *pStartDescriptor = pxCurDescriptor; } - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) else if( pEndDescriptor != NULL ) { ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; @@ -1236,7 +1236,7 @@ void HAL_ETH_RxLinkCallback( void ** pStart, void ** pEnd, uint8_t * buff, uint1 FreeRTOS_debug_printf( ( "HAL_ETH_RxLinkCallback: Buffer Dropped\n" ) ); NetworkBufferDescriptor_t * pxDescriptorToClear = pxCurDescriptor; do { - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) NetworkBufferDescriptor_t * const pxNext = pxDescriptorToClear->pxNextBuffer; #else NetworkBufferDescriptor_t * const pxNext = NULL; From 9365b8eba980d813a706991e97b3a5ddabf55aec Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 6 Jan 2024 05:48:21 -0500 Subject: [PATCH 33/68] remove a global --- .../NetworkInterface/STM32/NetworkInterface.c | 114 ++++++++++-------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index db96974717..c1dba0c2bb 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -131,7 +131,7 @@ #define niEMAC_USE_RMII ipconfigENABLE /*===========================================================================*/ -/* Enums */ +/* typedefs */ /*===========================================================================*/ /* Interrupt events to process: reception, transmission and error handling. */ @@ -156,6 +156,16 @@ typedef enum eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; +/* typedef struct xEMACData +{ + ETH_HandleTypeDef xEthHandle; + EthernetPhy_t xPhyObject; + TaskHandle_t xEMACTaskHandle; + SemaphoreHandle_t xTxMutex, xTxDescSem; + eMAC_INIT_STATUS_TYPE xMacInitStatus; + BaseType_t xEMACIndex; +} EMACData_t; */ + /*===========================================================================*/ /* Static Function Declarations */ /*===========================================================================*/ @@ -169,15 +179,15 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /* static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); */ /* static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); */ -static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ); +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); static portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ) __NO_RETURN; -static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ); +static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); -static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ); +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); @@ -192,9 +202,10 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* Static Variable Declarations */ /*===========================================================================*/ +/* static EMACData_t xEMACData; */ + static ETH_HandleTypeDef xEthHandle; -static NetworkInterface_t * pxMyInterface; static EthernetPhy_t xPhyObject; static TaskHandle_t xEMACTaskHandle; @@ -259,8 +270,8 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ) { BaseType_t xInitResult = pdFAIL; - ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + EthernetPhy_t * pxPhyObject = &xPhyObject; switch( xMacInitStatus ) { @@ -292,9 +303,9 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacPhyInit: - vPhyInitialise( &xPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); + vPhyInitialise( pxPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); - if( xPhyDiscover( &xPhyObject ) == 0 ) + if( xPhyDiscover( pxPhyObject ) == 0 ) { break; } @@ -303,7 +314,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacPhyStart: - if( prvPhyStart( pxEthHandle, pxInterface ) == pdFALSE ) + if( prvPhyStart( pxEthHandle, pxInterface, pxPhyObject ) == pdFALSE ) { break; } @@ -312,7 +323,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacTaskStart: - if( prvEMACTaskStart( pxEthHandle ) == pdFALSE ) + if( prvEMACTaskStart( pxInterface ) == pdFALSE ) { break; } @@ -347,10 +358,11 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; /* Zero-Copy Only */ configASSERT( xReleaseAfterSend == pdTRUE ); - if( ( xMacInitStatus == eMacInitComplete ) && ( xEthHandle.gState == HAL_ETH_STATE_STARTED ) ) + if( ( xMacInitStatus == eMacInitComplete ) && ( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) ) { if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ) ) { @@ -380,7 +392,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.Length = xTxBuffer.len; xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.pData = pxDescriptor; - if( HAL_ETH_Transmit_IT( &xEthHandle, &xTxConfig ) == HAL_OK ) + if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) { /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ xReleaseAfterSend = pdFALSE; @@ -389,9 +401,9 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N else { ( void ) xSemaphoreGive( xTxDescSem ); - configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - configASSERT( xEthHandle.gState == HAL_ETH_STATE_STARTED ); - if( xEthHandle.ErrorCode & HAL_ETH_ERROR_BUSY ) + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); + if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); } @@ -441,7 +453,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /* EMAC Task */ /*===========================================================================*/ -static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { UBaseType_t uxResult = 0; /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ @@ -462,7 +474,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) } configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); ++uxResult; - pxCurDescriptor->pxInterface = pxMyInterface; + pxCurDescriptor->pxInterface = pxInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); /* TODO: check pxEndPoint exists? Check it earlier before getting buffer? */ #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) @@ -506,13 +518,13 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) if( uxResult == 0 ) { - configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - /* ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); */ + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + /*( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) { ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); - } + }*/ } return ( ( BaseType_t ) ( uxResult > 0 ) ); @@ -522,8 +534,10 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle ) static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { - ETH_HandleTypeDef * pxEthHandle = ( ETH_HandleTypeDef * ) pvParameters; - configASSERT( pxEthHandle ); + NetworkInterface_t * pxInterface = ( NetworkInterface_t * ) pvParameters; + configASSERT( pxInterface ); + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + EthernetPhy_t * pxPhyObject = &xPhyObject; /* iptraceEMAC_TASK_STARTING(); */ @@ -536,7 +550,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { if( ( ulISREvents & eMacEventRx ) != 0 ) { - xResult = prvNetworkInterfaceInput( pxEthHandle ); + xResult = prvNetworkInterfaceInput( pxEthHandle, pxInterface ); } if( ( ulISREvents & eMacEventTx ) != 0 ) @@ -570,7 +584,8 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrEth ) != 0 ) { - configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ + /* configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); */ } if( ( ulISREvents & eMacEventErrMac ) != 0 ) @@ -587,15 +602,16 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ + /* configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); */ - if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != pdFALSE ) + if( xPhyCheckLinkStatus( pxPhyObject, xResult ) != pdFALSE ) { - if( prvGetPhyLinkStatus( pxMyInterface ) != pdFALSE ) + if( prvGetPhyLinkStatus( pxInterface ) != pdFALSE ) { if( pxEthHandle->gState == HAL_ETH_STATE_READY ) { /* Link Was Down */ - if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + if( prvMacUpdateConfig( pxEthHandle, pxPhyObject ) != pdFALSE ) { ( void ) HAL_ETH_Start_IT( pxEthHandle ); } @@ -607,7 +623,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_NETWORK_DOWN_EVENT ) ) /* ( void ) HAL_ETH_DeInit( pxEthHandle ); xMacInitStatus = eMacEthInit; */ - FreeRTOS_NetworkDown( pxMyInterface ); + FreeRTOS_NetworkDown( pxInterface ); #endif } } @@ -616,7 +632,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) /*---------------------------------------------------------------------------*/ -static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) +static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) { BaseType_t xResult = pdFALSE; @@ -660,7 +676,7 @@ static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) prvEMACHandlerTask, niEMAC_TASK_NAME, niEMAC_TASK_STACK_SIZE, - ( void * ) pxEthHandle, + ( void * ) pxInterface, niEMAC_TASK_PRIORITY, uxEMACTaskStack, &xEMACTaskTCB @@ -670,7 +686,7 @@ static BaseType_t prvEMACTaskStart( ETH_HandleTypeDef * pxEthHandle ) prvEMACHandlerTask, niEMAC_TASK_NAME, niEMAC_TASK_STACK_SIZE, - ( void * ) pxEthHandle, + ( void * ) pxInterface, niEMAC_TASK_PRIORITY, &xEMACTaskHandle ); @@ -794,7 +810,7 @@ static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa /*---------------------------------------------------------------------------*/ -static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -818,9 +834,9 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface #endif }; - if( xPhyConfigure( &xPhyObject, &xPhyProperties ) == 0 ) + if( xPhyConfigure( pxPhyObject, &xPhyProperties ) == 0 ) { - if( prvMacUpdateConfig( pxEthHandle ) != pdFALSE ) + if( prvMacUpdateConfig( pxEthHandle, pxPhyObject ) != pdFALSE ) { xResult = pdTRUE; } @@ -838,7 +854,7 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface /* MAC Helpers */ /*===========================================================================*/ -static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -853,17 +869,17 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle ) #if ( ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ - ( void ) xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - xMACConfig.DuplexMode = ( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - xMACConfig.Speed = ( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; + ( void ) xPhyStartAutoNegotiation( pxPhyObject, xPhyGetMask( pxPhyObject ) ); + xMACConfig.DuplexMode = ( pxPhyObject->xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + xMACConfig.Speed = ( pxPhyObject->xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; #else - xPhyObject.xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; - xPhyObject.xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + pxPhyObject->xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; + pxPhyObject->xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; /* ucMDI_X unused */ /* TODO: xPhyFixedValue always return 0 */ - ( void ) xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - xMACConfig.DuplexMode = xPhyObject.xPhyPreferences.ucDuplex; - xMACConfig.Speed = xPhyObject.xPhyPreferences.ucSpeed; + ( void ) xPhyFixedValue( pxPhyObject, xPhyGetMask( pxPhyObject ) ); + xMACConfig.DuplexMode = pxPhyObject->xPhyPreferences.ucDuplex; + xMACConfig.Speed = pxPhyObject->xPhyPreferences.ucSpeed; #endif if( HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ) == HAL_OK ) @@ -1142,7 +1158,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) } } - configASSERT( ( xEthHandle.ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); xSwitchRequired |= xHigherPriorityTaskWoken; } @@ -1285,7 +1301,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net ( void ) memset( pxInterface, '\0', sizeof( *pxInterface ) ); pxInterface->pcName = pcName; - /* TODO: use pvArgument to get xPhyObject/xEthHandle/xMacInitStatus? */ + /* TODO: use pvArgument to get xEMACData? */ + /* xEMACData.xEMACIndex = xEMACIndex; */ + /* pxInterface->pvArgument = ( void * ) &xEMACData; */ pxInterface->pvArgument = ( void * ) xEMACIndex; pxInterface->pfInitialise = prvNetworkInterfaceInitialise; pxInterface->pfOutput = prvNetworkInterfaceOutput; @@ -1293,9 +1311,7 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ - pxMyInterface = FreeRTOS_AddNetworkInterface( pxInterface ); - - return pxMyInterface; + return FreeRTOS_AddNetworkInterface( pxInterface ); } /*---------------------------------------------------------------------------*/ From fbb525717625fc11b3c009914d2cfbca98cd7684 Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 6 Jan 2024 09:08:57 -0500 Subject: [PATCH 34/68] prep for mac filtering --- .../NetworkInterface/STM32/NetworkInterface.c | 245 +++++++++++------- 1 file changed, 146 insertions(+), 99 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index c1dba0c2bb..de7e295876 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -44,6 +44,14 @@ /* FreeRTOS+TCP includes. */ #include "FreeRTOS_IP.h" #include "FreeRTOS_IP_Private.h" +#include "FreeRTOS_ARP.h" +#if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) || ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) + #include "FreeRTOS_DNS.h" +#endif +#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + #include "FreeRTOS_ND.h" +#endif +#include "FreeRTOS_Routing.h" #include "NetworkBufferManagement.h" #include "NetworkInterface.h" #include "phyHandling.h" @@ -120,8 +128,6 @@ #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" #define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" -/* #define niEMAC_PHY_COUNT 1 */ - #define niEMAC_AUTO_NEGOTIATION ipconfigENABLE #define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) @@ -362,88 +368,92 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /* Zero-Copy Only */ configASSERT( xReleaseAfterSend == pdTRUE ); - if( ( xMacInitStatus == eMacInitComplete ) && ( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) ) + do { - if( ( pxDescriptor != NULL ) && ( pxDescriptor->pucEthernetBuffer != NULL ) && ( pxDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ) ) + if( ( pxDescriptor == NULL ) || ( pxDescriptor->pucEthernetBuffer == NULL ) || ( pxDescriptor->xDataLength > niEMAC_DATA_BUFFER_SIZE ) ) { - if( prvGetPhyLinkStatus( pxInterface ) != pdFAIL ) - { - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) != pdFALSE ) - { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) - { - static ETH_TxPacketConfig xTxConfig = { - .CRCPadCtrl = ETH_CRC_PAD_INSERT, - #if ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ) - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, - .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, - #else - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, - .ChecksumCtrl = ETH_CHECKSUM_DISABLE, - #endif - }; - - ETH_BufferTypeDef xTxBuffer = { - .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, - .len = pxDescriptor->xDataLength, - .next = NULL - }; - - xTxConfig.Length = xTxBuffer.len; - xTxConfig.TxBuffer = &xTxBuffer; - xTxConfig.pData = pxDescriptor; - if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) - { - /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ - xReleaseAfterSend = pdFALSE; - xResult = pdPASS; - } - else - { - ( void ) xSemaphoreGive( xTxDescSem ); - configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); - if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); - } - } - ( void ) xSemaphoreGive( xTxMutex ); - } - else - { - ( void ) xSemaphoreGive( xTxDescSem ); - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); - } - } - else - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); - } - } - else - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); - } + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Descriptor\n" ) ); + break; + } + + if( xCheckLoopback( pxDescriptor, xReleaseAfterSend ) != pdFALSE ) + { + /* The packet has been sent back to the IP-task. + * The IP-task will further handle it. + * Do not release the descriptor. */ + xReleaseAfterSend = pdFALSE; + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Loopback\n" ) ); + break; + } + + if( ( xMacInitStatus != eMacInitComplete ) || ( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Interface Not Started\n" ) ); + break; + } + + if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); + break; + } + + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); + break; + } + + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); + ( void ) xSemaphoreGive( xTxDescSem ); + break; + } + + ETH_BufferTypeDef xTxBuffer = { + .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + + ETH_TxPacketConfig xTxConfig = { + .CRCPadCtrl = ETH_CRC_PAD_INSERT, + #if ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ) + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, + .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, + #else + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, + .ChecksumCtrl = ETH_CHECKSUM_DISABLE, + #endif + .Length = xTxBuffer.len, + .TxBuffer = &xTxBuffer, + .pData = pxDescriptor, + }; + + if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) + { + /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ + xReleaseAfterSend = pdFALSE; + xResult = pdPASS; } else { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Descriptor\n" ) ); + ( void ) xSemaphoreGive( xTxDescSem ); + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); + if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); + } } - } - else - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Eth Not Started\n" ) ); - } + ( void ) xSemaphoreGive( xTxMutex ); - if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend == pdTRUE ) && ( xResult == pdFAIL ) ) - { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); - } + } while( pdFALSE ); - if( xResult == pdFAIL ) + if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend == pdTRUE ) ) { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Failed\n" ) ); + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); } return xResult; @@ -467,16 +477,15 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { + ++uxResult; if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ continue; } configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); - ++uxResult; pxCurDescriptor->pxInterface = pxInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); - /* TODO: check pxEndPoint exists? Check it earlier before getting buffer? */ #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) if( pxStartDescriptor == NULL ) { @@ -757,26 +766,50 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - /* #if ( ipconfigIS_ENABLEDipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - ETH_MACFilterConfigTypeDef xFilterConfig; - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - #endif */ + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + /* xFilterConfig.PromiscuousMode = DISABLE; + xFilterConfig.ReceiveAllMode = DISABLE; + xFilterConfig.HachOrPerfectFilter = ENABLE; + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.HashMulticast = ENABLE; + xFilterConfig.PassAllMulticast = DISABLE; + xFilterConfig.SrcAddrFiltering = ENABLE; + xFilterConfig.SrcAddrInverseFiltering = DISABLE; + xFilterConfig.DestAddrInverseFiltering = DISABLE; + xFilterConfig.BroadcastFilter = DISABLE; + xFilterConfig.ControlPacketsFilter = DISABLE; */ + #endif + + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); + } #if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) ) - prvMACAddressConfig( pxEthHandle, xMDNS_MacAddress.ucBytes ); + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + prvMACAddressConfig( pxEthHandle, xMDNS_MacAddress.ucBytes ); + #endif #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, xMDNS_MACAddressIPv6.ucBytes ); #endif #endif #if ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) - prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddress.ucBytes ); + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddress.ucBytes ); + #endif #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddressIPv6.ucBytes ); #endif #endif - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + #endif + + /* for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) @@ -796,16 +829,14 @@ static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa { prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); } - #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - } + #endif + } */ #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); #endif - /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - #endif */ + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); } /*---------------------------------------------------------------------------*/ @@ -1222,30 +1253,30 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) /*---------------------------------------------------------------------------*/ -void HAL_ETH_RxLinkCallback( void ** pStart, void ** pEnd, uint8_t * buff, uint16_t usLength ) +void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff, uint16_t usLength ) { - NetworkBufferDescriptor_t ** const pStartDescriptor = ( NetworkBufferDescriptor_t ** ) pStart; - NetworkBufferDescriptor_t ** const pEndDescriptor = ( NetworkBufferDescriptor_t ** ) pEnd; - NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) buff ); + NetworkBufferDescriptor_t ** const ppxStartDescriptor = ( NetworkBufferDescriptor_t ** ) ppvStart; + NetworkBufferDescriptor_t ** const ppxEndDescriptor = ( NetworkBufferDescriptor_t ** ) ppvEnd; + NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) pucBuff ); if( prvAcceptPacket( pxCurDescriptor, usLength ) == pdTRUE ) { pxCurDescriptor->xDataLength = usLength; #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) pxCurDescriptor->pxNextBuffer = NULL; #endif - if( *pStartDescriptor == NULL ) + if( *ppxStartDescriptor == NULL ) { - *pStartDescriptor = pxCurDescriptor; + *ppxStartDescriptor = pxCurDescriptor; } #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) - else if( pEndDescriptor != NULL ) + else if( ppxEndDescriptor != NULL ) { - ( *pEndDescriptor )->pxNextBuffer = pxCurDescriptor; + ( *ppxEndDescriptor )->pxNextBuffer = pxCurDescriptor; } #endif - *pEndDescriptor = pxCurDescriptor; + *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ - configASSERT( *pStartDescriptor == *pEndDescriptor ); + configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); } else { @@ -1304,6 +1335,7 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* TODO: use pvArgument to get xEMACData? */ /* xEMACData.xEMACIndex = xEMACIndex; */ /* pxInterface->pvArgument = ( void * ) &xEMACData; */ + /* pxInterface->pvArgument = pvPortMalloc( sizeof( EMACData_t ) ); */ pxInterface->pvArgument = ( void * ) xEMACIndex; pxInterface->pfInitialise = prvNetworkInterfaceInitialise; pxInterface->pfOutput = prvNetworkInterfaceOutput; @@ -1315,3 +1347,18 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net } /*---------------------------------------------------------------------------*/ + +#if ( ipconfigIS_ENABLED( ipconfigIPv4_BACKWARD_COMPATIBLE ) ) + +/* Do not call the following function directly. It is there for downward compatibility. + * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point + * objects. See the description in FreeRTOS_Routing.h. */ + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) + { + pxSTM32_FillInterfaceDescriptor( xEMACIndex, pxInterface ); + } + +#endif + +/*---------------------------------------------------------------------------*/ From 7987744959c83e3f188df74182d655d9e78adbbd Mon Sep 17 00:00:00 2001 From: Holden Date: Sat, 6 Jan 2024 16:42:13 -0500 Subject: [PATCH 35/68] add HAL_ETH_MspInit example --- .../NetworkInterface/STM32/NetworkInterface.c | 142 +++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index de7e295876..b06b732662 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -215,6 +215,7 @@ static ETH_HandleTypeDef xEthHandle; static EthernetPhy_t xPhyObject; static TaskHandle_t xEMACTaskHandle; + static SemaphoreHandle_t xTxMutex, xTxDescSem; static volatile BaseType_t xSwitchRequired; @@ -1361,4 +1362,143 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net #endif -/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* Sample HAL_ETH_MspInit */ +/*===========================================================================*/ + +#if 0 +/** + * @brief Initializes the ETH MSP. + * @param heth: ETH handle + * @retval None +*/ +void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) +{ + if( heth->Instance == ETH ) + { + /* Enable ETHERNET clock */ + #if defined( STM32F4 ) || defined( STM32F7 ) + __HAL_RCC_ETH_CLK_ENABLE(); + #elif defined( STM32H5 ) + __HAL_RCC_ETH_CLK_ENABLE(); + __HAL_RCC_ETHTX_CLK_ENABLE(); + __HAL_RCC_ETHRX_CLK_ENABLE(); + #elif defined( STM32H7) + __HAL_RCC_ETH1MAC_CLK_ENABLE(); + __HAL_RCC_ETH1TX_CLK_ENABLE(); + __HAL_RCC_ETH1RX_CLK_ENABLE(); + #endif + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + + /* Ethernet pins configuration ************************************************/ + /* + Common Pins + ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin + ETH_MDIO ---------------------> + ETH_RXD0 ---------------------> + ETH_RXD1 ---------------------> + ETH_TX_EN --------------------> + ETH_TXD0 ---------------------> + ETH_TXD1 ---------------------> + + RMII Specific Pins + ETH_REF_CLK ------------------> + ETH_CRS_DV -------------------> + + MII Specific Pins + ETH_RX_CLK -------------------> + ETH_RX_ER --------------------> + ETH_RX_DV --------------------> + ETH_RXD2 ---------------------> + ETH_RXD3 ---------------------> + ETH_TX_CLK -------------------> + ETH_TXD2 ---------------------> + ETH_TXD3 ---------------------> + ETH_CRS ----------------------> + ETH_COL ----------------------> + */ + + GPIO_InitTypeDef GPIO_InitStructure = { 0 }; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + + GPIO_InitStructure.Pin = ETH_MDC_Pin; + HAL_GPIO_Init(ETH_MDC_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_MDIO_Pin; + HAL_GPIO_Init(ETH_MDIO_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RXD0_Pin; + HAL_GPIO_Init(ETH_RXD0_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RXD1_Pin; + HAL_GPIO_Init(ETH_RXD1_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TX_EN_Pin; + HAL_GPIO_Init(ETH_TX_EN_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TXD0_Pin; + HAL_GPIO_Init(ETH_TXD0_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TXD1_Pin; + HAL_GPIO_Init(ETH_TXD1_Port, &GPIO_InitStructure); + + if( heth->Init.MediaInterface == HAL_ETH_RMII_MODE ) + { + GPIO_InitStructure.Pin = ETH_REF_CLK_Pin; + HAL_GPIO_Init(ETH_REF_CLK_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_CRS_DV_Pin; + HAL_GPIO_Init(ETH_CRS_DV_Port, &GPIO_InitStructure); + } + else if( heth->Init.MediaInterface == HAL_ETH_MII_MODE ) + { + GPIO_InitStructure.Pin = ETH_RX_CLK_Pin; + HAL_GPIO_Init(ETH_RX_CLK_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RX_ER_Pin; + HAL_GPIO_Init(ETH_RX_ER_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RX_DV_Pin; + HAL_GPIO_Init(ETH_RX_ER_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RXD2_Pin; + HAL_GPIO_Init(ETH_RXD2_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_RXD3_Pin; + HAL_GPIO_Init(ETH_RXD3_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TX_CLK_Pin; + HAL_GPIO_Init(ETH_TX_CLK_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TXD2_Pin; + HAL_GPIO_Init(ETH_TXD2_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_TXD3_Pin; + HAL_GPIO_Init(ETH_TXD3_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_COL_Pin; + HAL_GPIO_Init(ETH_COL_Port, &GPIO_InitStructure); + + GPIO_InitStructure.Pin = ETH_CRS_Pin; + HAL_GPIO_Init(ETH_CRS_Port, &GPIO_InitStructure); + } + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_FREERTOS_INTERRUPT_PRIORITY, 0 ); + HAL_NVIC_EnableIRQ( ETH_IRQn ); + } +} + +#endif /* 0 */ From d4c83863bd2afc57f019f9077c3f3d88fb84b85b Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 7 Jan 2024 00:44:22 -0500 Subject: [PATCH 36/68] prep packet and frame filtering --- .../NetworkInterface/STM32/NetworkInterface.c | 193 +++++++++++++++--- 1 file changed, 160 insertions(+), 33 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index b06b732662..fbb14a5359 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -52,6 +52,9 @@ #include "FreeRTOS_ND.h" #endif #include "FreeRTOS_Routing.h" +#if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + #include "FreeRTOS_Sockets.h" +#endif #include "NetworkBufferManagement.h" #include "NetworkInterface.h" #include "phyHandling.h" @@ -77,7 +80,21 @@ #if ( ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) - #warning Consider enabling checksum offloading for NetworkInterface + #warning Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM/ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface + #endif +#endif + +#if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) + #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface + #endif +#endif + +#if defined( STM32H5 ) || defined ( STM32H7 ) + #if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) + #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface + #endif #endif #endif @@ -176,32 +193,45 @@ typedef enum /* Static Function Declarations */ /*===========================================================================*/ +/* Phy Hooks */ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); +/* Network Interface Access Hooks */ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); /* static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); */ /* static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); */ +/* EMAC Task */ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); static portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ) __NO_RETURN; static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); +/* EMAC Init */ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); +/* MAC Helpers */ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucAddr ); +/* Filter Helpers */ +/*#if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + static void prvUpdateFrameFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +#endif */ +/* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +#endif */ /* static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ); */ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ); +/* Network Interface Definition */ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); /*===========================================================================*/ @@ -292,18 +322,6 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac break; } - /* - { - ETH_DMAConfigTypeDef xDMAConfig; - ( void ) HAL_ETH_GetDMAConfig( pxEthHandle, &xDMAConfig ); - xDMAConfig. - if( HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ) != HAL_OK ) - { - break; - } - } - */ - prvInitMACAddresses( pxEthHandle, pxInterface ); xMacInitStatus = eMacPhyInit; @@ -460,6 +478,24 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N return xResult; } +/*---------------------------------------------------------------------------*/ + +#if 0 + +static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) +{ + +} + +/*---------------------------------------------------------------------------*/ + +static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) +{ + +} + +#endif /* if 0 */ + /*===========================================================================*/ /* EMAC Task */ /*===========================================================================*/ @@ -611,6 +647,10 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } } + /* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + prvUpdatePacketFilter( pxEthHandle, pxInterface ); + #endif */ + /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ /* configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); */ @@ -760,6 +800,20 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo } */ } + /* + ETH_DMAConfigTypeDef xDMAConfig; + ( void ) HAL_ETH_GetDMAConfig( pxEthHandle, &xDMAConfig ); + xDMAConfig. + if( HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ) != HAL_OK ) + { + break; + } + */ + + /* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + prvUpdatePacketFilter( pxEthHandle, pxInterface ); + #endif */ + return xResult; } @@ -767,22 +821,6 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - ETH_MACFilterConfigTypeDef xFilterConfig; - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - /* xFilterConfig.PromiscuousMode = DISABLE; - xFilterConfig.ReceiveAllMode = DISABLE; - xFilterConfig.HachOrPerfectFilter = ENABLE; - xFilterConfig.HashUnicast = ENABLE; - xFilterConfig.HashMulticast = ENABLE; - xFilterConfig.PassAllMulticast = DISABLE; - xFilterConfig.SrcAddrFiltering = ENABLE; - xFilterConfig.SrcAddrInverseFiltering = DISABLE; - xFilterConfig.DestAddrInverseFiltering = DISABLE; - xFilterConfig.BroadcastFilter = DISABLE; - xFilterConfig.ControlPacketsFilter = DISABLE; */ - #endif - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); @@ -837,7 +875,10 @@ static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); #endif - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + /* TODO: Move this into prvMACAddressConfig? Also determine changes that need to be done based on added/removed allowed MAC address */ + /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + prvUpdateFrameFilter( pxEthHandle, pxInterface ); + #endif */ } /*---------------------------------------------------------------------------*/ @@ -1017,13 +1058,97 @@ static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucA default: break; } + + /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + prvUpdateFrameFilter( pxEthHandle, pxInterface ); + #endif */ } /*===========================================================================*/ -/* Rx Helpers */ +/* Filter Helpers */ /*===========================================================================*/ #if 0 + +#if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + +static void prvUpdateFrameFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +{ + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + + /* xFilterConfig.PromiscuousMode = DISABLE; + xFilterConfig.ReceiveAllMode = DISABLE; + xFilterConfig.HachOrPerfectFilter = ENABLE; + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.HashMulticast = ENABLE; + xFilterConfig.PassAllMulticast = DISABLE; + xFilterConfig.SrcAddrFiltering = ENABLE; + xFilterConfig.SrcAddrInverseFiltering = DISABLE; + xFilterConfig.DestAddrInverseFiltering = DISABLE; + xFilterConfig.BroadcastFilter = DISABLE; + xFilterConfig.ControlPacketsFilter = DISABLE; */ + + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); +} + +#endif /* if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) */ + +#endif /* if 0 */ + + +/*---------------------------------------------------------------------------*/ + +#if 0 + +#if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + +/* TODO: Where to put this? Should it be triggered by a NetworkInterface_t hook? */ +static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +{ + HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); + + ETH_L3FilterConfigTypeDef xL3FilterConfig; + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH/ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE/ETH_L3_SRC_ADDR_INVERSE_MATCH_ENABLE/ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE/ETH_L3_DEST_ADDR_INVERSE_MATCH_ENABLE/ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = ; + xL3FilterConfig.DestAddrHigherBitsMatch = ; + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + xL3FilterConfig.Ip4SrcAddr = ; + xL3FilterConfig.Ip4DestAddr = ; + #endif + #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + xL3FilterConfig.Ip6Addr = ; + #endif + + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + + + ETH_L4FilterConfigTypeDef xL4FilterConfig; + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH/ETH_L4_TCP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE/ETH_L4_SRC_PORT_INVERSE_MATCH_ENABLE/ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE/ETH_L4_DEST_PORT_INVERSE_MATCH_ENABLE/ETH_L4_DEST_PORT_MATCH_DISABLE; + xL4FilterConfig.SourcePort = ; + xL4FilterConfig.DestinationPort = ; + + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); +} + +#endif /* if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) */ + +#endif + +/*---------------------------------------------------------------------------*/ + +#if 0 + #if ( defined( STM32F4 ) || defined( STM32F7 ) ) #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR @@ -1074,7 +1199,8 @@ static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8 return xResult; } -#endif + +#endif /* if 0 */ /*---------------------------------------------------------------------------*/ @@ -1367,6 +1493,7 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /*===========================================================================*/ #if 0 + /** * @brief Initializes the ETH MSP. * @param heth: ETH handle @@ -1501,4 +1628,4 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) } } -#endif /* 0 */ +#endif /* if 0 */ From 8a37763985f97cbbeb259955ce2600cffcf85e8e Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 10 Jan 2024 14:51:36 -0500 Subject: [PATCH 37/68] add sample mpu config --- .../NetworkInterface/STM32/NetworkInterface.c | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index fbb14a5359..148eaab79f 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1598,7 +1598,7 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) HAL_GPIO_Init(ETH_RX_ER_Port, &GPIO_InitStructure); GPIO_InitStructure.Pin = ETH_RX_DV_Pin; - HAL_GPIO_Init(ETH_RX_ER_Port, &GPIO_InitStructure); + HAL_GPIO_Init(ETH_RX_DV_Port, &GPIO_InitStructure); GPIO_InitStructure.Pin = ETH_RXD2_Pin; HAL_GPIO_Init(ETH_RXD2_Port, &GPIO_InitStructure); @@ -1629,3 +1629,50 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) } #endif /* if 0 */ + +/*===========================================================================*/ +/* Sample MPU Config */ +/*===========================================================================*/ + +#if 0 + +void MPU_Config(void) +{ + extern uint8_t __ETH_BUFFERS_START, __ETH_DESCRIPTORS_START; + + MPU_Region_InitTypeDef MPU_InitStruct; + + HAL_MPU_Disable(); + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} + +#endif /* if 0 */ From 17ee34133aeb90e716c807ffc26b49f028517260 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 17 Jan 2024 00:03:43 -0500 Subject: [PATCH 38/68] mac filter improvements --- .../NetworkInterface/STM32/NetworkInterface.c | 622 ++++++++++-------- 1 file changed, 336 insertions(+), 286 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 148eaab79f..f892de1172 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1,8 +1,3 @@ -/* - * Some constants, hardware definitions and comments taken from ST's HAL driver - * library, COPYRIGHT(c) 2017 STMicroelectronics. - */ - /* * FreeRTOS+TCP * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. @@ -30,6 +25,8 @@ * http://www.FreeRTOS.org */ +/*---------------------------------------------------------------------------*/ + /* Standard includes. */ #include #include @@ -45,14 +42,14 @@ #include "FreeRTOS_IP.h" #include "FreeRTOS_IP_Private.h" #include "FreeRTOS_ARP.h" -#if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) || ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) +#if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) || ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) #include "FreeRTOS_DNS.h" #endif -#if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) +#if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) #include "FreeRTOS_ND.h" #endif #include "FreeRTOS_Routing.h" -#if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) +#if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) #include "FreeRTOS_Sockets.h" #endif #include "NetworkBufferManagement.h" @@ -74,37 +71,39 @@ #error Unknown STM32 Family for NetworkInterface #endif +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Config Checks */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ -#if ( ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) - #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) +#if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) #warning Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM/ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface #endif #endif -#if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) +#if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface #endif #endif #if defined( STM32H5 ) || defined ( STM32H7 ) - #if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) - #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) + #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface #endif #endif #endif -#if ( ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) ) - #if ( ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) ) +#if ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) #warning Unsupported ipconfigNETWORK_MTU size #endif #endif -#if ( ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) ) +#if ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) #error Task Notifications must be enabled for NetworkInterface #endif @@ -112,9 +111,11 @@ #error HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface #endif +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Macros */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ #define niEMAC_TX_DESC_SECTION ".TxDescripSection" #define niEMAC_RX_DESC_SECTION ".RxDescripSection" @@ -131,9 +132,9 @@ #define niEMAC_CACHE_LINE_SIZE 32U #endif -#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT ) & ( ( uint32_t ) ~portBYTE_ALIGNMENT_MASK ) ) +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) #define niEMAC_TOTAL_ALIGNMENT_MASK ( niEMAC_CACHE_LINE_SIZE - 1U ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) #define niEMAC_MAX_BLOCK_TIME_MS 100U #define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U @@ -153,9 +154,23 @@ #define niEMAC_USE_RMII ipconfigENABLE +#define niEMAC_MAX_LINKED_TX_PACKETS 1 + +/* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ +#define niEMAC_CRC_POLY 0x04C11DB7 + +/* TODO: Enabled and use interrupts for phy instead of polling? */ +/*#define niPHY_ISR_AN_COMPLETE 0x0040 +#define niPHY_ISR_LINK_DOWN 0x0010 + +#define niPHY_IMR_AN_COMPLETE 0x0040 +#define niPHY_IMR_LINK_DOWN 0x0010*/ + +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* typedefs */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ /* Interrupt events to process: reception, transmission and error handling. */ typedef enum { @@ -184,14 +199,21 @@ typedef enum ETH_HandleTypeDef xEthHandle; EthernetPhy_t xPhyObject; TaskHandle_t xEMACTaskHandle; - SemaphoreHandle_t xTxMutex, xTxDescSem; + SemaphoreHandle_t xTxMutex; + BaseType_t xSwitchRequired; eMAC_INIT_STATUS_TYPE xMacInitStatus; BaseType_t xEMACIndex; + MACAddress_t xMatchedMacAddresses[ 3 ]; + UBaseType_t uxMACEntry; } EMACData_t; */ +/* TODO: need a data structure to assist in adding/removing allowed addresses */ + +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Static Function Declarations */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ /* Phy Hooks */ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); @@ -201,8 +223,8 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); -/* static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); */ -/* static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); */ +static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); /* EMAC Task */ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); @@ -211,21 +233,18 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); -static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); -/* MAC Helpers */ +/* EMAC Helpers */ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); -static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ); -static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ); -static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); -static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucAddr ); +static uint32_t prvCalcCrc32( const uint8_t * pucMAC ); +static void prvUpdateMacHashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); +static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ); +static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ); /* Filter Helpers */ -/*#if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) - static void prvUpdateFrameFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -#endif */ -/* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) +/* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); #endif */ /* static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ); */ @@ -234,9 +253,11 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes /* Network Interface Definition */ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Static Variable Declarations */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ /* static EMACData_t xEMACData; */ @@ -246,15 +267,23 @@ static EthernetPhy_t xPhyObject; static TaskHandle_t xEMACTaskHandle; -static SemaphoreHandle_t xTxMutex, xTxDescSem; +static SemaphoreHandle_t xTxMutex; -static volatile BaseType_t xSwitchRequired; +static BaseType_t xSwitchRequired; static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; +/* Store previously matched addresses for easy checking */ +static MACAddress_t xMatchedMacAddresses[ 3 ] = { 0 }; + +/* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ +static UBaseType_t uxMACEntry = ETH_MAC_ADDRESS1; + +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Phy Hooks */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { @@ -282,9 +311,11 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin return xResult; } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Network Interface Access Hooks */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) { @@ -322,7 +353,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac break; } - prvInitMACAddresses( pxEthHandle, pxInterface ); + prvInitMacAddresses( pxEthHandle, pxInterface ); xMacInitStatus = eMacPhyInit; /* fallthrough */ @@ -417,39 +448,53 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); - break; - } - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); - ( void ) xSemaphoreGive( xTxDescSem ); + // TODO: Can we queue it? break; } - ETH_BufferTypeDef xTxBuffer = { - .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, - .len = pxDescriptor->xDataLength, - .next = NULL - }; - - ETH_TxPacketConfig xTxConfig = { + static ETH_TxPacketConfig xTxConfig = { .CRCPadCtrl = ETH_CRC_PAD_INSERT, - #if ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ) + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, #else .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, .ChecksumCtrl = ETH_CHECKSUM_DISABLE, #endif - .Length = xTxBuffer.len, - .TxBuffer = &xTxBuffer, - .pData = pxDescriptor, }; + xTxConfig.pData = pxDescriptor; + #if ipconfigIS_DISABLED( ipconfigUSE_LINKED_RX_MESSAGES ) + ETH_BufferTypeDef xTxBuffer = { + .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + + xTxConfig.TxBuffer = &xTxBuffer; + xTxConfig.Length = xTxBuffer.len; + #else + /* Support the possibility of linked Tx messages */ + ETH_BufferTypeDef xTxBuffer[ niEMAC_MAX_LINKED_TX_PACKETS ]; + + xTxConfig.TxBuffer = xTxBuffer; + xTxConfig.Length = 0; + UBaseType_t uxIndex = 0; + NetworkBufferDescriptor_t * pxCurDescriptor = pxDescriptor; + while( pxCurDescriptor != NULL ) + { + ETH_BufferTypeDef * pxCurTxBuffer = &xTxBuffer[ uxIndex++ ]; + pxCurTxBuffer->buffer = ( uint8_t * ) pxCurDescriptor->pucEthernetBuffer; + pxCurTxBuffer->len = pxCurDescriptor->xDataLength; + pxCurTxBuffer->next = ( uxIndex < ARRAY_SIZE( xTxBuffer ) ) ? &xTxBuffer[ uxIndex ] : NULL; + xTxConfig.Length += pxCurTxBuffer->len; + pxCurDescriptor = pxCurDescriptor->pxNextBuffer; + }; + #endif + if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) { /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ @@ -458,7 +503,6 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N } else { - ( void ) xSemaphoreGive( xTxDescSem ); configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) @@ -470,9 +514,9 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N } while( pdFALSE ); - if( ( pxDescriptor != NULL ) && ( xReleaseAfterSend == pdTRUE ) ) + if( xReleaseAfterSend == pdTRUE ) { - vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + prvReleaseNetworkBufferDescriptor( pxDescriptor ); } return xResult; @@ -480,37 +524,126 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /*---------------------------------------------------------------------------*/ -#if 0 - static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { + configASSERT( pucMacAddress ); + + const BaseType_t xIsMulticast = ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) ? pdTRUE : pdFALSE; + + BaseType_t xFound = pdFALSE; + for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) + { + /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ + if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + /* Already assigned this mac address */ + xFound = pdTRUE; + } + } + + if( xFound == pdFALSE ) + { + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + + switch( uxMACEntry ) + { + case ETH_MAC_ADDRESS1: + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); + ( void ) memcpy( xMatchedMacAddresses[ 0 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); + uxMACEntry = ETH_MAC_ADDRESS2; + /* Only need to do this once, don't repeat for following addresses */ + if( xFilterConfig.HachOrPerfectFilter == DISABLE ) + { + xFilterConfig.HachOrPerfectFilter = ENABLE; + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + } + break; + + case ETH_MAC_ADDRESS2: + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); + ( void ) memcpy( xMatchedMacAddresses[ 1 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); + uxMACEntry = ETH_MAC_ADDRESS3; + break; + + case ETH_MAC_ADDRESS3: + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); + ( void ) memcpy( xMatchedMacAddresses[ 2 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); + /* Just used to show that the address registers are filled */ + uxMACEntry = ETH_MAC_ADDRESS0; + break; + + case ETH_MAC_ADDRESS0: + prvUpdateMacHashFilter( pxEthHandle, pucMacAddress ); + if( xIsMulticast == pdTRUE ) + { + if( xFilterConfig.HashMulticast == DISABLE ) + { + xFilterConfig.HashMulticast = ENABLE; + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + } + } + else + { + if( xFilterConfig.HashUnicast == DISABLE ) + { + xFilterConfig.HashUnicast = ENABLE; + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + } + } + break; + default: + configASSERT( pdFALSE ); + break; + } + } } /*---------------------------------------------------------------------------*/ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { + configASSERT( pucMacAddress ); -} + const BaseType_t xIsMulticast = ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) ? pdTRUE : pdFALSE; -#endif /* if 0 */ + BaseType_t xFound = pdFALSE; + for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) + { + /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ + if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + /* Already assigned this mac address */ + xFound = pdTRUE; + } + } + if( xFound == pdTRUE ) + { + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + + } +} + +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* EMAC Task */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { UBaseType_t uxResult = 0; /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; - IPStackEvent_t xRxEvent; - xRxEvent.eEventType = eNetworkRxEvent; while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { @@ -521,9 +654,10 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net continue; } configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); + pxCurDescriptor->pxInterface = pxInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) if( pxStartDescriptor == NULL ) { pxStartDescriptor = pxCurDescriptor; @@ -534,33 +668,16 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net } pxEndDescriptor = pxCurDescriptor; #else - xRxEvent.pvData = ( void * ) pxCurDescriptor; - if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) - { - iptraceETHERNET_RX_EVENT_LOST(); - FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); - vReleaseNetworkBufferAndDescriptor( pxCurDescriptor ); - } - #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) */ + prvSendRxEvent( pxCurDescriptor ); + #endif } - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) if( uxResult > 0 ) { - xRxEvent.pvData = ( void * ) pxStartDescriptor; - if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) - { - iptraceETHERNET_RX_EVENT_LOST(); - FreeRTOS_debug_printf( ( "prvNetworkInterfaceInput: xSendEventStructToIPTask failed\n" ) ); - NetworkBufferDescriptor_t * pxDescriptorToClear = pxStartDescriptor; - do { - NetworkBufferDescriptor_t * pxNext = pxDescriptorToClear->pxNextBuffer; - vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); - pxDescriptorToClear = pxNext; - } while( pxDescriptorToClear != NULL ); - } + prvSendRxEvent( pxStartDescriptor ); } - #endif /* if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) */ + #endif if( uxResult == 0 ) { @@ -621,10 +738,6 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) { ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); - while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > pxEthHandle->TxDescList.BuffersInUse ) - { - ( void ) xSemaphoreGive( xTxDescSem ); - } } } @@ -647,7 +760,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } } - /* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + /* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) prvUpdatePacketFilter( pxEthHandle, pxInterface ); #endif */ @@ -688,7 +801,7 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) if( xTxMutex == NULL ) { - #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) + #if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) static StaticSemaphore_t xTxMutexBuf; xTxMutex = xSemaphoreCreateMutexStatic( &xTxMutexBuf ); #else @@ -698,28 +811,9 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); } - if( xTxDescSem == NULL ) + if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) ) { - #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) - static StaticSemaphore_t xTxDescSemBuf; - xTxDescSem = xSemaphoreCreateCountingStatic( - ( UBaseType_t ) ETH_TX_DESC_CNT, - ( UBaseType_t ) ETH_TX_DESC_CNT, - &xTxDescSemBuf - ); - #else - xTxDescSem = xSemaphoreCreateCounting( - ( UBaseType_t ) ETH_TX_DESC_CNT, - ( UBaseType_t ) ETH_TX_DESC_CNT - ); - #endif - configASSERT( xTxDescSem != NULL ); - vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); - } - - if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) - { - #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) + #if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; static StaticTask_t xEMACTaskTCB; xEMACTaskHandle = xTaskCreateStatic( @@ -751,9 +845,11 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) return xResult; } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* EMAC Init */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ) { @@ -761,7 +857,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo pxEthHandle->Instance = ETH; - #if ( ipconfigIS_ENABLED( niEMAC_USE_RMII ) ) + #if ipconfigIS_ENABLED( niEMAC_USE_RMII ) pxEthHandle->Init.MediaInterface = HAL_ETH_RMII_MODE; #else pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE; @@ -794,10 +890,6 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo { xResult = pdTRUE; } - /* else - { - pxEthHandle->ErrorCode & HAL_ETH_ERROR_TIMEOUT - } */ } /* @@ -810,7 +902,12 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo } */ - /* #if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + /* #if defined( STM32H5 ) || defined ( STM32H7 ) + HAL_ETHEx_EnableARPOffload( pxEthHandle ); + HAL_ETHEx_SetARPAddressMatch( pxEthHandle ); + #endif */ + + /* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) prvUpdatePacketFilter( pxEthHandle, pxInterface ); #endif */ @@ -819,66 +916,57 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo /*---------------------------------------------------------------------------*/ -static void prvInitMACAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); - } + ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - #if ( ipconfigIS_ENABLED( ipconfigUSE_MDNS ) ) - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) - prvMACAddressConfig( pxEthHandle, xMDNS_MacAddress.ucBytes ); - #endif - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - prvMACAddressConfig( pxEthHandle, xMDNS_MACAddressIPv6.ucBytes ); - #endif - #endif + /* These are always disabled */ + xFilterConfig.SrcAddrFiltering = DISABLE; + xFilterConfig.SrcAddrInverseFiltering = DISABLE; + xFilterConfig.DestAddrInverseFiltering = DISABLE; + xFilterConfig.BroadcastFilter = DISABLE; + xFilterConfig.ControlPacketsFilter = DISABLE; - #if ( ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) ) - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) - prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddress.ucBytes ); - #endif - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - prvMACAddressConfig( pxEthHandle, xLLMNR_MacAddressIPv6.ucBytes ); - #endif - #endif + /* All all if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is disabled */ + xFilterConfig.PromiscuousMode = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; + xFilterConfig.ReceiveAllMode = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; + xFilterConfig.PassAllMulticast = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); - #endif + /* These are determined later, just set default disable */ + xFilterConfig.HachOrPerfectFilter = DISABLE; + xFilterConfig.HashUnicast = DISABLE; + xFilterConfig.HashMulticast = DISABLE; - /* for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - if( pxEndPoint->bits.bIPv6 != pdFALSE_UNSIGNED ) - { - const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] = { - 0x33, - 0x33, - 0xff, - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 13 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 14 ], - pxEndPoint->ipv6_settings.xIPAddress.ucBytes[ 15 ] - }; - prvMACAddressConfig( pxEthHandle, ucMACAddress ); - } - #else - if( pxEthHandle->Init.MACAddr != ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes ) - { - prvMACAddressConfig( pxEthHandle, pxEndPoint->xMACAddress.ucBytes ); - } + /* Update the initial configuration, it may be changed again in prvAddAllowedMACAddress */ + ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); + + /* If we are filtering frame types then handle placing target MAC Addresses in filters */ + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); + } + + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) + prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); + #endif + #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) + prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); + #endif #endif - } */ - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - prvMACAddressConfig( pxEthHandle, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) + prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); + #endif + #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) + prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); + #endif + #endif #endif - - /* TODO: Move this into prvMACAddressConfig? Also determine changes that need to be done based on added/removed allowed MAC address */ - /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - prvUpdateFrameFilter( pxEthHandle, pxInterface ); - #endif */ } /*---------------------------------------------------------------------------*/ @@ -890,7 +978,7 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { const PhyProperties_t xPhyProperties = { - #if ( ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) + #if ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) .ucSpeed = PHY_SPEED_AUTO, .ucDuplex = PHY_DUPLEX_AUTO, #else @@ -898,7 +986,7 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface .ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF, #endif - #if ( ipconfigIS_ENABLED( niEMAC_AUTO_CROSS ) ) + #if ipconfigIS_ENABLED( niEMAC_AUTO_CROSS ) .ucMDI_X = PHY_MDIX_AUTO, #elif ( ipconfigIS_ENABLED( niEMAC_CROSSED_LINK ) ) .ucMDI_X = PHY_MDIX_CROSSED, @@ -923,9 +1011,11 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface return xResult; } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ -/* MAC Helpers */ +/* EMAC Helpers */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ) { @@ -940,7 +1030,7 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); - #if ( ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) + #if ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ ( void ) xPhyStartAutoNegotiation( pxPhyObject, xPhyGetMask( pxPhyObject ) ); xMACConfig.DuplexMode = ( pxPhyObject->xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; @@ -966,62 +1056,51 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP /*---------------------------------------------------------------------------*/ /* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ -static uint32_t prvComputeCRC32_MAC( const uint8_t * pucMAC ) +static uint32_t prvCalcCrc32( const uint8_t * pucMAC ) { uint32_t ulCRC32 = 0xFFFFFFFF; - for( UBaseType_t i = 0; i < 6; ++i ) + for( uint8_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) { - ulCRC32 ^= ( uint32_t ) pucMAC[ i ]; + ulCRC32 ^= ( uint32_t ) pucMAC[ ucIndex ]; - for( UBaseType_t j = 0; j < 8; ++j ) + for( uint8_t ucJndex = 0; ucJndex < 8; ++ucJndex ) { + const BaseType_t xTemp = ulCRC32 & 1; ulCRC32 >>= 1; - if( ulCRC32 & 1 ) + if( xTemp ) { - /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ - ulCRC32 ^= __RBIT( 0x04C11DB7 ); + ulCRC32 ^= __RBIT( niEMAC_CRC_POLY ); } } } - ulCRC32 = ~( ulCRC32 ); - return ulCRC32; -} - -/*---------------------------------------------------------------------------*/ - -/* Compute the hash value of a given MAC address to index the bits in the Hash Table */ -static uint32_t prvComputeEthernet_MACHash( const uint8_t * pucMAC ) -{ - /* Calculate the 32-bit CRC for the MAC */ - const uint32_t ulCRC32 = prvComputeCRC32_MAC( pucMAC ); - /* Perform bitwise reversal on the CRC32 */ - const uint32_t ulHash = __RBIT( ulCRC32 ); - - /* Take the upper 6 bits of the above result */ - return ( ulHash >> 26 ); + return __RBIT( ~ulCRC32 ); } /*---------------------------------------------------------------------------*/ /* Update the Hash Table Registers with hash value of the given MAC address */ -static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) +static void prvUpdateMacHashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) { static uint32_t ulHashTable[ 2 ]; - const uint32_t ulHash = prvComputeEthernet_MACHash( pucMAC ); + /* Calculate the 32-bit CRC for the MAC */ + const uint32_t ulHash = prvCalcCrc32( pucMAC ); + + /* Take the upper 6 bits of the above result */ + const uint8_t ucEntry = ( ulHash >> 26 ) & 0x3F; /* Use the upper or lower Hash Table Registers * to set the required bit based on the ulHash */ - if( ulHash < 32 ) + if( ucEntry < 32 ) { - ulHashTable[ 0 ] = ulHash; + ulHashTable[ 0 ] |= ( 1 << ucEntry ); } else { - ulHashTable[ 1 ] = ulHash; + ulHashTable[ 1 ] |= ( 1 << ( ucEntry % 32 ) ); } ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); @@ -1029,79 +1108,46 @@ static void prvSetMAC_HashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t /*---------------------------------------------------------------------------*/ -static void prvMACAddressConfig( ETH_HandleTypeDef * pxEthHandle, uint8_t * pucAddr ) +static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ) { - /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ - static UBaseType_t uxMACEntry = ETH_MAC_ADDRESS1; - - switch( uxMACEntry ) + NetworkBufferDescriptor_t * pxDescriptorToClear = pxDescriptor; + while( pxDescriptorToClear != NULL ) { - case ETH_MAC_ADDRESS1: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); - uxMACEntry = ETH_MAC_ADDRESS2; - break; - - case ETH_MAC_ADDRESS2: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); - uxMACEntry = ETH_MAC_ADDRESS3; - break; - - case ETH_MAC_ADDRESS3: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, pucAddr ); - uxMACEntry = ETH_MAC_ADDRESS0; - break; + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) + NetworkBufferDescriptor_t * const pxNext = pxDescriptorToClear->pxNextBuffer; + #else + NetworkBufferDescriptor_t * const pxNext = NULL; + #endif + vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); + pxDescriptorToClear = pxNext; + }; +} - case ETH_MAC_ADDRESS0: - prvSetMAC_HashFilter( pxEthHandle, pucAddr ); - break; +/*---------------------------------------------------------------------------*/ - default: - break; +static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) +{ + const IPStackEvent_t xRxEvent = { + .eEventType = eNetworkRxEvent, + .pvData = ( void * ) pxDescriptor + }; + if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) + { + iptraceETHERNET_RX_EVENT_LOST(); + FreeRTOS_debug_printf( ( "prvSendRxEvent: xSendEventStructToIPTask failed\n" ) ); + prvReleaseNetworkBufferDescriptor( pxDescriptor ); } - - /* #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - prvUpdateFrameFilter( pxEthHandle, pxInterface ); - #endif */ } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Filter Helpers */ /*===========================================================================*/ - -#if 0 - -#if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - -static void prvUpdateFrameFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) -{ - ETH_MACFilterConfigTypeDef xFilterConfig; - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - - /* xFilterConfig.PromiscuousMode = DISABLE; - xFilterConfig.ReceiveAllMode = DISABLE; - xFilterConfig.HachOrPerfectFilter = ENABLE; - xFilterConfig.HashUnicast = ENABLE; - xFilterConfig.HashMulticast = ENABLE; - xFilterConfig.PassAllMulticast = DISABLE; - xFilterConfig.SrcAddrFiltering = ENABLE; - xFilterConfig.SrcAddrInverseFiltering = DISABLE; - xFilterConfig.DestAddrInverseFiltering = DISABLE; - xFilterConfig.BroadcastFilter = DISABLE; - xFilterConfig.ControlPacketsFilter = DISABLE; */ - - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); -} - -#endif /* if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) */ - -#endif /* if 0 */ - - /*---------------------------------------------------------------------------*/ #if 0 -#if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) +#if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) /* TODO: Where to put this? Should it be triggered by a NetworkInterface_t hook? */ static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) @@ -1141,7 +1187,7 @@ static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInter HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); } -#endif /* if ( ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) */ +#endif /* if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) */ #endif @@ -1149,7 +1195,7 @@ static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInter #if 0 -#if ( defined( STM32F4 ) || defined( STM32F7 ) ) +#if defined( STM32F4 ) || defined( STM32F7 ) #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR @@ -1163,7 +1209,7 @@ static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8 { BaseType_t xResult = pdFALSE; - #if ( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) const UBaseType_t uxPayloadType = READ_BIT( heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_PT ) const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); @@ -1172,13 +1218,13 @@ static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8 case ETH_IP_PAYLOAD_UNKNOWN: case ETH_IP_PAYLOAD_UDP: if( ( xPortHasUdpSocket( xUDPHeader->usDestinationPort ) ) - #if( ipconfigUSE_DNS == 1 ) * DNS is also UDP. * + #if ipconfigUSE_DNS == 1 * DNS is also UDP. * || ( xUDPHeader->usSourcePort == FreeRTOS_ntohs( ipDNS_PORT ) ) #endif - #if( ipconfigUSE_LLMNR == 1 ) * LLMNR is also UDP. * + #if ipconfigUSE_LLMNR == 1 * LLMNR is also UDP. * || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) #endif - #if( ipconfigUSE_NBNS == 1 ) * NBNS is also UDP. * + #if ipconfigUSE_NBNS == 1 * NBNS is also UDP. * || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) #endif ) @@ -1225,7 +1271,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes } */ - #if ( ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) xResult = pdTRUE; #else /* TODO: Handle this in hardware via HAL_ETH_SetMACFilterConfig */ @@ -1252,9 +1298,11 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes return xResult; } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* IRQ Handlers */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ void ETH_IRQHandler( void ) { @@ -1286,7 +1334,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) #if defined( STM32F4 ) || defined ( STM32F7 ) if( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) { - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ } if( pxEthHandle->DMAErrorCode & ETH_DMASR_RBUS ) @@ -1296,7 +1344,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) #elif defined( STM32H5 ) || defined ( STM32H7 ) if( pxEthHandle->DMAErrorCode & ETH_DMACSR_TBU ) { - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ } if( pxEthHandle->DMAErrorCode & ETH_DMACSR_RBU ) @@ -1361,9 +1409,11 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) xSwitchRequired |= xHigherPriorityTaskWoken; } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* HAL Tx/Rx Callbacks */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) { @@ -1388,14 +1438,14 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff if( prvAcceptPacket( pxCurDescriptor, usLength ) == pdTRUE ) { pxCurDescriptor->xDataLength = usLength; - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) pxCurDescriptor->pxNextBuffer = NULL; #endif if( *ppxStartDescriptor == NULL ) { *ppxStartDescriptor = pxCurDescriptor; } - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) else if( ppxEndDescriptor != NULL ) { ( *ppxEndDescriptor )->pxNextBuffer = pxCurDescriptor; @@ -1408,16 +1458,7 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff else { FreeRTOS_debug_printf( ( "HAL_ETH_RxLinkCallback: Buffer Dropped\n" ) ); - NetworkBufferDescriptor_t * pxDescriptorToClear = pxCurDescriptor; - do { - #if ( ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) ) - NetworkBufferDescriptor_t * const pxNext = pxDescriptorToClear->pxNextBuffer; - #else - NetworkBufferDescriptor_t * const pxNext = NULL; - #endif - vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); - pxDescriptorToClear = pxNext; - } while( pxDescriptorToClear != NULL ); + prvReleaseNetworkBufferDescriptor( pxCurDescriptor ); } } @@ -1426,13 +1467,14 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) { NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) pulBuff; - vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); - ( void ) xSemaphoreGive( xTxDescSem ); + prvReleaseNetworkBufferDescriptor( pxNetworkBuffer ); } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Buffer Allocation */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { @@ -1447,9 +1489,11 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB } } +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Network Interface Definition */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { @@ -1475,7 +1519,7 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /*---------------------------------------------------------------------------*/ -#if ( ipconfigIS_ENABLED( ipconfigIPv4_BACKWARD_COMPATIBLE ) ) +#if ipconfigIS_ENABLED( ipconfigIPv4_BACKWARD_COMPATIBLE ) /* Do not call the following function directly. It is there for downward compatibility. * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point @@ -1488,9 +1532,11 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net #endif +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Sample HAL_ETH_MspInit */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ #if 0 @@ -1630,9 +1676,11 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) #endif /* if 0 */ +/*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Sample MPU Config */ /*===========================================================================*/ +/*---------------------------------------------------------------------------*/ #if 0 @@ -1676,3 +1724,5 @@ void MPU_Config(void) } #endif /* if 0 */ + +/*---------------------------------------------------------------------------*/ From 9edef7a1c95d282a44527afe97f1491eeaf6afc0 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 17 Jan 2024 16:20:26 -0500 Subject: [PATCH 39/68] improve some checks --- .../NetworkInterface/STM32/NetworkInterface.c | 127 ++++++++++-------- 1 file changed, 69 insertions(+), 58 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index f892de1172..0b9adb6369 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -111,6 +111,12 @@ #error HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface #endif +#if ( defined( STM32F4 ) || defined( STM32F7 ) ) && defined( ETH_RX_BUF_SIZE ) + #if ( niEMAC_DATA_BUFFER_SIZE != ETH_RX_BUF_SIZE ) + #warning "As of F7 V1.17.1 && F4 V1.28.0, a bug exists in the ETH HAL Driver where ETH_RX_BUF_SIZE is used instead of RxBuffLen, so ETH_RX_BUF_SIZE must == niEMAC_DATA_BUFFER_SIZE" + #endif +#endif + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Macros */ @@ -121,20 +127,19 @@ #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -/* - * TODO: Cache Handling - * This is only for F7 which uses M7, H5 uses M33, how does this work with dual core H7 M7/M4? - * Can probably align by portBYTE_ALIGNMENT if not cached - */ -#ifdef __SCB_DCACHE_LINE_SIZE - #define niEMAC_CACHE_LINE_SIZE __SCB_DCACHE_LINE_SIZE +/* TODO: Cache Handling, only for m7 */ +#if __DCACHE_PRESENT + #define niEMAC_CACHE_ENABLED ( SCB->CCR & SCB_CCR_DC_Msk ) + #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE + #define niEMAC_ALIGNMENT_MASK ( niEMAC_ALIGNMENT - 1U ) #else - #define niEMAC_CACHE_LINE_SIZE 32U + #define niEMAC_CACHE_ENABLED pdFALSE + #define niEMAC_ALIGNMENT portBYTE_ALIGNMENT + #define niEMAC_ALIGNMENT_MASK portBYTE_ALIGNMENT_MASK #endif #define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) -#define niEMAC_TOTAL_ALIGNMENT_MASK ( niEMAC_CACHE_LINE_SIZE - 1U ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_CACHE_LINE_SIZE ) & ~niEMAC_TOTAL_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_ALIGNMENT_MASK ) & ~niEMAC_ALIGNMENT_MASK ) #define niEMAC_MAX_BLOCK_TIME_MS 100U #define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U @@ -144,13 +149,12 @@ #define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" -#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" #define niEMAC_AUTO_NEGOTIATION ipconfigENABLE #define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) +#define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) #define niEMAC_USE_RMII ipconfigENABLE @@ -166,6 +170,8 @@ #define niPHY_IMR_AN_COMPLETE 0x0040 #define niPHY_IMR_LINK_DOWN 0x0010*/ +#define niEMAC_MAC_IS_MULTICAST( pucMacAddress ) ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* typedefs */ @@ -224,11 +230,11 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); -static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); +//static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); /* EMAC Task */ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -static portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ) __NO_RETURN; +static __NO_RETURN portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ); static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ @@ -451,7 +457,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); - // TODO: Can we queue it? + /* TODO: Can we queue it? */ break; } @@ -528,7 +534,7 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { configASSERT( pucMacAddress ); - const BaseType_t xIsMulticast = ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) ? pdTRUE : pdFALSE; + const BaseType_t xIsMulticast = niEMAC_MAC_IS_MULTICAST( pucMacAddress ); BaseType_t xFound = pdFALSE; for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) @@ -602,12 +608,12 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) } /*---------------------------------------------------------------------------*/ - +#if 0 static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { configASSERT( pucMacAddress ); - const BaseType_t xIsMulticast = ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) ? pdTRUE : pdFALSE; + /* const BaseType_t xIsMulticast = niEMAC_MAC_IS_MULTICAST( pucMacAddress ); */ BaseType_t xFound = pdFALSE; for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) @@ -628,7 +634,7 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) } } - +#endif /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* EMAC Task */ @@ -866,9 +872,12 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); configASSERT( pxEthHandle->Init.RxBuffLen % 4U == 0 ); + #if ( defined( STM32F4 ) || defined( STM32F7 ) ) && defined( ETH_RX_BUF_SIZE ) + configASSERT( pxEthHandle->Init.RxBuffLen == ETH_RX_BUF_SIZE ); + #endif - static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); + static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); pxEthHandle->Init.TxDesc = xDMADescTx; pxEthHandle->Init.RxDesc = xDMADescRx; @@ -903,14 +912,19 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo */ /* #if defined( STM32H5 ) || defined ( STM32H7 ) - HAL_ETHEx_EnableARPOffload( pxEthHandle ); HAL_ETHEx_SetARPAddressMatch( pxEthHandle ); + HAL_ETHEx_EnableARPOffload( pxEthHandle ); #endif */ /* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) prvUpdatePacketFilter( pxEthHandle, pxInterface ); #endif */ + configASSERT( NVIC_GetEnableIRQ( ETH_IRQn ) != 0 ); + uint32_t ulPreemptPriority, ulSubPriority; + HAL_NVIC_GetPriority( ETH_IRQn, HAL_NVIC_GetPriorityGrouping(), &ulPreemptPriority, &ulSubPriority ); + configASSERT( ulPreemptPriority >= configMAX_FREERTOS_INTERRUPT_PRIORITY ); + return xResult; } @@ -1253,47 +1267,41 @@ static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8 static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ) { BaseType_t xResult = pdFALSE; + do + { + uint32_t ulErrorCode = 0; + ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); + if( ulErrorCode != 0 ) + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); + break; + } - uint32_t ulErrorCode = 0; - ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); + if( usLength > niEMAC_DATA_BUFFER_SIZE ) + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); + break; + } - if ( ulErrorCode == 0 ) - { - if( usLength <= niEMAC_DATA_BUFFER_SIZE ) + /* if( prvAcceptPayload( &xEthHandle, pxDescriptor->pucEthernetBuffer ) != pdTRUE ) { - /* if( prvAcceptPayload( &xEthHandle, pxDescriptor->pucEthernetBuffer ) != pdFALSE ) - { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Payload discarded\n" ) ); + break; + } */ - } - else + #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Payload discarded\n" ) ); + FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); + break; } - */ + #else + // prvUpdatePacketFilter should have set this filter up previously + #endif - #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) - xResult = pdTRUE; - #else - /* TODO: Handle this in hardware via HAL_ETH_SetMACFilterConfig */ - if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) == eProcessBuffer ) - { - xResult = pdTRUE; - } - else - { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); - } - #endif - } - else - { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); - } - } - else - { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); - } + xResult = pdTRUE; + + } while( pdFALSE ); return xResult; } @@ -1327,7 +1335,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { /* Fatal bus error occurred */ /* eMacEventErrDma */ - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrEth, eSetBits, &xHigherPriorityTaskWoken ); + /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrEth, eSetBits, &xHigherPriorityTaskWoken ); */ } else { @@ -1420,6 +1428,7 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { + /* TODO: Should any other checks be performed on pxBufferDescriptor? */ *ppucBuff = pxBufferDescriptor->pucEthernetBuffer; } else @@ -1478,7 +1487,7 @@ void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_CACHE_LINE_SIZE ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_ALIGNMENT ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); configASSERT( xBufferAllocFixedSize == pdTRUE ); @@ -1686,6 +1695,8 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) void MPU_Config(void) { + /* TODO: Usage based on if niEMAC_CACHE_ENABLED */ + extern uint8_t __ETH_BUFFERS_START, __ETH_DESCRIPTORS_START; MPU_Region_InitTypeDef MPU_InitStruct; From 71b5eebc860695b226c1dacdab9809567319bdd7 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 18 Jan 2024 08:22:02 -0500 Subject: [PATCH 40/68] config improvements --- .../NetworkInterface/STM32/NetworkInterface.c | 397 +++++++++--------- 1 file changed, 194 insertions(+), 203 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 0b9adb6369..6fc553d803 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -66,9 +66,9 @@ #elif defined( STM32H5 ) #include "stm32h5xx_hal.h" #elif defined( STM32F2 ) - #error This NetworkInterface is incompatible with STM32F2 - Use Legacy NetworkInterface + #error "This NetworkInterface is incompatible with STM32F2 - Use Legacy NetworkInterface" #else - #error Unknown STM32 Family for NetworkInterface + #error "Unknown STM32 Family for NetworkInterface" #endif /*---------------------------------------------------------------------------*/ @@ -79,36 +79,36 @@ #if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM/ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface + #warning "Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM/ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface" #endif #endif #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" #endif #endif -#if defined( STM32H5 ) || defined ( STM32H7 ) - #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface - #endif +/* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. + * So, don't use this macro, and filter anyways in the mean time. */ +/* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" #endif -#endif +#endif */ #if ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning Unsupported ipconfigNETWORK_MTU size + #warning "Unsupported ipconfigNETWORK_MTU size" #endif #endif #if ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) - #error Task Notifications must be enabled for NetworkInterface + #error "Task Notifications must be enabled for NetworkInterface" #endif #ifndef HAL_ETH_MODULE_ENABLED - #error HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface + #error "HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface" #endif #if ( defined( STM32F4 ) || defined( STM32F7 ) ) && defined( ETH_RX_BUF_SIZE ) @@ -123,19 +123,24 @@ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ +#if defined( STM32F7 ) || defined( STM32F4 ) + #define niEMAC_STM32FX +#elif defined( STM32H7 ) || defined( STM32H5 ) + #define niEMAC_STM32HX +#endif + #define niEMAC_TX_DESC_SECTION ".TxDescripSection" #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -/* TODO: Cache Handling, only for m7 */ -#if __DCACHE_PRESENT - #define niEMAC_CACHE_ENABLED ( SCB->CCR & SCB_CCR_DC_Msk ) +#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + // #define niEMAC_MPU_ENABLED ( ( MPU->CTRL & MPU_CTRL_ENABLE_Msk ) != 0 ) /* TODO: Check if regions are enabled and cacheable is set correctly for descriptors and buffers */ + // #define niEMAC_CACHE_ENABLED ( !niEMAC_MPU_ENABLED && ( SCB->CCR & SCB_CCR_DC_Msk ) ) #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE #define niEMAC_ALIGNMENT_MASK ( niEMAC_ALIGNMENT - 1U ) #else - #define niEMAC_CACHE_ENABLED pdFALSE - #define niEMAC_ALIGNMENT portBYTE_ALIGNMENT - #define niEMAC_ALIGNMENT_MASK portBYTE_ALIGNMENT_MASK + #define niEMAC_ALIGNMENT portBYTE_ALIGNMENT /* or should this always be 4? */ + #define niEMAC_ALIGNMENT_MASK portBYTE_ALIGNMENT_MASK /* or should this always be 3? */ #endif #define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) @@ -239,7 +244,7 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); /* EMAC Helpers */ @@ -250,10 +255,9 @@ static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ); /* Filter Helpers */ -/* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -#endif */ -/* static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ); */ +#ifdef niEMAC_STM32HX + static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); +#endif static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ); /* Network Interface Definition */ @@ -359,8 +363,6 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac break; } - prvInitMacAddresses( pxEthHandle, pxInterface ); - xMacInitStatus = eMacPhyInit; /* fallthrough */ @@ -482,6 +484,15 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.Length = xTxBuffer.len; + + /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + if( niEMAC_CACHE_ENABLED ) + { + uint8_t * pucDataStart = xTxBuffer.buffer; + uint8_t * pucLineStart = ( uint8_t * ) ( ( uint32_t ) pucDataStart & ~niEMAC_ALIGNMENT_MASK ); + SCB_CleanDCache_by_Addr( ( uint32_t * ) pucLineStart, xTxBuffer.len + ( pucDataStart - pucLineStart ) ); + } + #endif*/ #else /* Support the possibility of linked Tx messages */ ETH_BufferTypeDef xTxBuffer[ niEMAC_MAX_LINKED_TX_PACKETS ]; @@ -497,6 +508,14 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N pxCurTxBuffer->len = pxCurDescriptor->xDataLength; pxCurTxBuffer->next = ( uxIndex < ARRAY_SIZE( xTxBuffer ) ) ? &xTxBuffer[ uxIndex ] : NULL; xTxConfig.Length += pxCurTxBuffer->len; + /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + if( niEMAC_CACHE_ENABLED ) + { + uint8_t * pucDataStart = pxCurTxBuffer->buffer; + uint8_t * pucLineStart = ( uint8_t * ) ( ( uint32_t ) pucDataStart & ~niEMAC_ALIGNMENT_MASK ); + SCB_CleanDCache_by_Addr( ( uint32_t * ) pucLineStart, pxCurTxBuffer->len + ( pucDataStart - pucLineStart ) ); + } + #endif*/ pxCurDescriptor = pxCurDescriptor->pxNextBuffer; }; #endif @@ -534,8 +553,6 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { configASSERT( pucMacAddress ); - const BaseType_t xIsMulticast = niEMAC_MAC_IS_MULTICAST( pucMacAddress ); - BaseType_t xFound = pdFALSE; for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) { @@ -551,7 +568,6 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; ETH_MACFilterConfigTypeDef xFilterConfig; - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); switch( uxMACEntry ) { @@ -560,6 +576,7 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) ( void ) memcpy( xMatchedMacAddresses[ 0 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); uxMACEntry = ETH_MAC_ADDRESS2; /* Only need to do this once, don't repeat for following addresses */ + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); if( xFilterConfig.HachOrPerfectFilter == DISABLE ) { xFilterConfig.HachOrPerfectFilter = ENABLE; @@ -582,7 +599,8 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) case ETH_MAC_ADDRESS0: prvUpdateMacHashFilter( pxEthHandle, pucMacAddress ); - if( xIsMulticast == pdTRUE ) + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + if( niEMAC_MAC_IS_MULTICAST( pucMacAddress ) == pdTRUE ) { if( xFilterConfig.HashMulticast == DISABLE ) { @@ -608,7 +626,9 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) } /*---------------------------------------------------------------------------*/ + #if 0 + static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { configASSERT( pucMacAddress ); @@ -634,7 +654,9 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) } } + #endif + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* EMAC Task */ @@ -643,7 +665,8 @@ static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { - UBaseType_t uxResult = 0; + BaseType_t xResult = pdFALSE; + UBaseType_t uxCount = 0; /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; @@ -653,7 +676,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { - ++uxResult; + ++uxCount; if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ @@ -678,25 +701,24 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net #endif } - #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) - if( uxResult > 0 ) - { + if( uxCount > 0 ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) prvSendRxEvent( pxStartDescriptor ); - } - #endif - - if( uxResult == 0 ) + #endif + xResult = pdTRUE; + } + else { configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - /*( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrRx, eSetBits ); - - if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) + /*if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) { ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); }*/ + xResult = pdFALSE; } - return ( ( BaseType_t ) ( uxResult > 0 ) ); + return xResult; } /*---------------------------------------------------------------------------*/ @@ -733,7 +755,8 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrRx ) != 0 ) { - /*do { + /*do + { xResult = ( prvNetworkInterfaceInput() > 0 ); } while ( xResult != pdFALSE ); xResult = pdTRUE;*/ @@ -766,7 +789,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) } } - /* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + /* #ifdef niEMAC_STM32HX prvUpdatePacketFilter( pxEthHandle, pxInterface ); #endif */ @@ -872,7 +895,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); configASSERT( pxEthHandle->Init.RxBuffLen % 4U == 0 ); - #if ( defined( STM32F4 ) || defined( STM32F7 ) ) && defined( ETH_RX_BUF_SIZE ) + #if ( defined( niEMAC_STM32FX ) && defined( ETH_RX_BUF_SIZE ) ) configASSERT( pxEthHandle->Init.RxBuffLen == ETH_RX_BUF_SIZE ); #endif @@ -890,64 +913,75 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo { pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; - #if defined( STM32F7 ) || defined( STM32F4 ) + #ifdef niEMAC_STM32FX /* This function doesn't get called in Fxx driver */ HAL_ETH_SetMDIOClockRange( pxEthHandle ); #endif if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) { + /* ETH_DMAConfigTypeDef xDMAConfig; + xDMAConfig.SecondPacketOperate = ENABLE; + ( void ) HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ); */ + + /* #ifdef niEMAC_STM32HX + HAL_ETHEx_DisableARPOffload( pxEthHandle ); + HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); + HAL_ETHEx_EnableARPOffload( pxEthHandle ); + #endif */ + + #ifdef niEMAC_STM32HX + prvInitPacketFilter( pxEthHandle, pxInterface ); + #endif + + prvInitMacAddresses( pxEthHandle, pxInterface ); + xResult = pdTRUE; } } - /* - ETH_DMAConfigTypeDef xDMAConfig; - ( void ) HAL_ETH_GetDMAConfig( pxEthHandle, &xDMAConfig ); - xDMAConfig. - if( HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ) != HAL_OK ) + if( xResult == pdTRUE ) { - break; + configASSERT( NVIC_GetEnableIRQ( ETH_IRQn ) != 0 ); + uint32_t ulPreemptPriority, ulSubPriority; + HAL_NVIC_GetPriority( ETH_IRQn, HAL_NVIC_GetPriorityGrouping(), &ulPreemptPriority, &ulSubPriority ); + configASSERT( ulPreemptPriority >= configMAX_FREERTOS_INTERRUPT_PRIORITY ); + if( ulPreemptPriority < configMAX_FREERTOS_INTERRUPT_PRIORITY ) + { + HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_FREERTOS_INTERRUPT_PRIORITY, 0 ); + } + if( NVIC_GetEnableIRQ( ETH_IRQn ) == 0 ) + { + HAL_NVIC_EnableIRQ( ETH_IRQn ); + } } - */ - - /* #if defined( STM32H5 ) || defined ( STM32H7 ) - HAL_ETHEx_SetARPAddressMatch( pxEthHandle ); - HAL_ETHEx_EnableARPOffload( pxEthHandle ); - #endif */ - - /* #if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - prvUpdatePacketFilter( pxEthHandle, pxInterface ); - #endif */ - - configASSERT( NVIC_GetEnableIRQ( ETH_IRQn ) != 0 ); - uint32_t ulPreemptPriority, ulSubPriority; - HAL_NVIC_GetPriority( ETH_IRQn, HAL_NVIC_GetPriorityGrouping(), &ulPreemptPriority, &ulSubPriority ); - configASSERT( ulPreemptPriority >= configMAX_FREERTOS_INTERRUPT_PRIORITY ); return xResult; } /*---------------------------------------------------------------------------*/ -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ) { ETH_MACFilterConfigTypeDef xFilterConfig; ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - /* These are always disabled */ + /* These are always constant */ + xFilterConfig.PromiscuousMode = DISABLE; + xFilterConfig.ReceiveAllMode = DISABLE; + xFilterConfig.PassAllMulticast = DISABLE; + xFilterConfig.BroadcastFilter = ENABLE; xFilterConfig.SrcAddrFiltering = DISABLE; xFilterConfig.SrcAddrInverseFiltering = DISABLE; xFilterConfig.DestAddrInverseFiltering = DISABLE; - xFilterConfig.BroadcastFilter = DISABLE; - xFilterConfig.ControlPacketsFilter = DISABLE; - - /* All all if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is disabled */ - xFilterConfig.PromiscuousMode = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; - xFilterConfig.ReceiveAllMode = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; - xFilterConfig.PassAllMulticast = ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ? ENABLE : DISABLE; + #ifdef niEMAC_STM32FX + /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ + xFilterConfig.ControlPacketsFilter = ETH_MACFFR_PCF_BlockAll; + #else + xFilterConfig.ControlPacketsFilter = ETH_CTRLPACKETS_BLOCK_ALL; + #endif - /* These are determined later, just set default disable */ + /* These are determined later in prvAddAllowedMACAddress, just set default disable */ xFilterConfig.HachOrPerfectFilter = DISABLE; xFilterConfig.HashUnicast = DISABLE; xFilterConfig.HashMulticast = DISABLE; @@ -955,30 +989,27 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa /* Update the initial configuration, it may be changed again in prvAddAllowedMACAddress */ ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - /* If we are filtering frame types then handle placing target MAC Addresses in filters */ - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); - } + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); + } - #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) - #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) - prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); - #endif - #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) - prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); - #endif + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) + prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); #endif + #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) + prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); + #endif + #endif - #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); - #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) - prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); - #endif - #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) - prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); - #endif + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) + prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); + #endif + #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) + prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); #endif #endif } @@ -1159,108 +1190,56 @@ static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -#if 0 - -#if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) +#ifdef niEMAC_STM32HX -/* TODO: Where to put this? Should it be triggered by a NetworkInterface_t hook? */ -static void prvUpdatePacketFilter( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ) { HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); - ETH_L3FilterConfigTypeDef xL3FilterConfig; - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH/ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE/ETH_L3_SRC_ADDR_INVERSE_MATCH_ENABLE/ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE/ETH_L3_DEST_ADDR_INVERSE_MATCH_ENABLE/ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = ; - xL3FilterConfig.DestAddrHigherBitsMatch = ; - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) - xL3FilterConfig.Ip4SrcAddr = ; - xL3FilterConfig.Ip4DestAddr = ; - #endif - #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - xL3FilterConfig.Ip6Addr = ; - #endif - - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - + const uint32_t uxL3FilterIds[ 2 ] = { ETH_L3_FILTER_0, ETH_L3_FILTER_1 }; + uint32_t uxL3FilterIdIndex = 0; - ETH_L4FilterConfigTypeDef xL4FilterConfig; - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - - xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH/ETH_L4_TCP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE/ETH_L4_SRC_PORT_INVERSE_MATCH_ENABLE/ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE/ETH_L4_DEST_PORT_INVERSE_MATCH_ENABLE/ETH_L4_DEST_PORT_MATCH_DISABLE; - xL4FilterConfig.SourcePort = ; - xL4FilterConfig.DestinationPort = ; - - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - - HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); -} - -#endif /* if ( defined( STM32H5 ) || defined ( STM32H7 ) ) && ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) */ - -#endif - -/*---------------------------------------------------------------------------*/ - -#if 0 - -#if defined( STM32F4 ) || defined( STM32F7 ) - #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR - #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR - - #define ETH_IP_PAYLOAD_UNKNOWN 0x00000000U - #define ETH_IP_PAYLOAD_UDP ETH_DMAPTPRXDESC_IPPT_UDP - #define ETH_IP_PAYLOAD_TCP ETH_DMAPTPRXDESC_IPPT_TCP - #define ETH_IP_PAYLOAD_ICMPN ETH_DMAPTPRXDESC_IPPT_ICMP -#endif - -static BaseType_t prvAcceptPayload( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucEthernetBuffer ) -{ - BaseType_t xResult = pdFALSE; - - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - const UBaseType_t uxPayloadType = READ_BIT( heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_PT ) - const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; - const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); - switch( uxPayloadType ) + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + ETH_L3FilterConfigTypeDef xL3FilterConfig; + /* #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) */ + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) { - case ETH_IP_PAYLOAD_UNKNOWN: - case ETH_IP_PAYLOAD_UDP: - if( ( xPortHasUdpSocket( xUDPHeader->usDestinationPort ) ) - #if ipconfigUSE_DNS == 1 * DNS is also UDP. * - || ( xUDPHeader->usSourcePort == FreeRTOS_ntohs( ipDNS_PORT ) ) - #endif - #if ipconfigUSE_LLMNR == 1 * LLMNR is also UDP. * - || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipLLMNR_PORT ) ) - #endif - #if ipconfigUSE_NBNS == 1 * NBNS is also UDP. * - || ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipNBNS_PORT ) ) - #endif - ) - { - xResult = pdTRUE; - } - else - { - xResult = pdFALSE; - } - break; + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex ], &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex++ ], &xL3FilterConfig ); + } + /* #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex ], &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex++ ], &xL3FilterConfig ); + } - case ETH_IP_PAYLOAD_TCP: - case ETH_IP_PAYLOAD_ICMPN: - default: + if( uxL3FilterIdIndex >= ARRAY_SIZE( uxL3FilterIds ) ) + { + break; } - #endif + } - return xResult; + /* TODO: This needs to be live updated based on sockets? */ + /* ETH_L4FilterConfigTypeDef xL4FilterConfigUDP; + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfigUDP ); + xL4FilterConfigUDP.Protocol = ETH_L4_UDP_MATCH; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfigUDP ); + + #if ( ipconfigIS_ENABLED( ipconfigUSE_TCP ) ) + ETH_L4FilterConfigTypeDef xL4FilterConfigTCP; + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfigTCP ); + xL4FilterConfigTCP.Protocol = ETH_L4_TCP_MATCH; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfigTCP ); + #endif */ + + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); } -#endif /* if 0 */ +#endif /* ifdef niEMAC_STM32HX */ /*---------------------------------------------------------------------------*/ @@ -1283,20 +1262,22 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes break; } - /* if( prvAcceptPayload( &xEthHandle, pxDescriptor->pucEthernetBuffer ) != pdTRUE ) - { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Payload discarded\n" ) ); - break; - } */ + /* TODO: Create a eConsiderPacketForProcessing */ + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + if( eConsiderPacketForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet discarded\n" ) ); + break; + } + #endif - #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + /* TODO: Should we do this even if it is handled in hardware too? */ + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); break; } - #else - // prvUpdatePacketFilter should have set this filter up previously #endif xResult = pdTRUE; @@ -1339,7 +1320,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) } else { - #if defined( STM32F4 ) || defined ( STM32F7 ) + #ifdef niEMAC_STM32FX if( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) { /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ @@ -1349,7 +1330,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); */ } - #elif defined( STM32H5 ) || defined ( STM32H7 ) + #elif defined( niEMAC_STM32HX ) if( pxEthHandle->DMAErrorCode & ETH_DMACSR_TBU ) { /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ @@ -1463,6 +1444,13 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); + + /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + if( niEMAC_CACHE_ENABLED ) + { + SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pucBuff, usLength ); + } + #endif*/ } else { @@ -1475,6 +1463,7 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) { + configASSERT( pulBuff ); NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) pulBuff; prvReleaseNetworkBufferDescriptor( pxNetworkBuffer ); } @@ -1533,8 +1522,7 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* Do not call the following function directly. It is there for downward compatibility. * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point * objects. See the description in FreeRTOS_Routing.h. */ - NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, - NetworkInterface_t * pxInterface ) + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) { pxSTM32_FillInterfaceDescriptor( xEMACIndex, pxInterface ); } @@ -1559,7 +1547,7 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) if( heth->Instance == ETH ) { /* Enable ETHERNET clock */ - #if defined( STM32F4 ) || defined( STM32F7 ) + #ifdef niEMAC_STM32FX __HAL_RCC_ETH_CLK_ENABLE(); #elif defined( STM32H5 ) __HAL_RCC_ETH_CLK_ENABLE(); @@ -1616,7 +1604,9 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) GPIO_InitStructure.Alternate = GPIO_AF11_ETH; GPIO_InitStructure.Pin = ETH_MDC_Pin; + GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; HAL_GPIO_Init(ETH_MDC_Port, &GPIO_InitStructure); + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Pin = ETH_MDIO_Pin; HAL_GPIO_Init(ETH_MDIO_Port, &GPIO_InitStructure); @@ -1695,6 +1685,7 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) void MPU_Config(void) { + /* #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) */ /* TODO: Usage based on if niEMAC_CACHE_ENABLED */ extern uint8_t __ETH_BUFFERS_START, __ETH_DESCRIPTORS_START; From 423b5cfb74ab351fe9dc73ceb6909dd16c8baa72 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 18 Jan 2024 08:22:57 -0500 Subject: [PATCH 41/68] cache fixes --- .../NetworkInterface/STM32/NetworkInterface.c | 175 +++++++++--------- 1 file changed, 86 insertions(+), 89 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 6fc553d803..fc057c8761 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -134,8 +134,9 @@ #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - // #define niEMAC_MPU_ENABLED ( ( MPU->CTRL & MPU_CTRL_ENABLE_Msk ) != 0 ) /* TODO: Check if regions are enabled and cacheable is set correctly for descriptors and buffers */ - // #define niEMAC_CACHE_ENABLED ( !niEMAC_MPU_ENABLED && ( SCB->CCR & SCB_CCR_DC_Msk ) ) + #define niEMAC_CACHEABLE + #define niEMAC_MPU_ENABLED ipconfigENABLE + #define niEMAC_CACHE_ENABLED ( ipconfigIS_DISABLED( niEMAC_MPU_ENABLED ) && ( ( SCB->CCR & SCB_CCR_DC_Msk ) != 0 ) ) #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE #define niEMAC_ALIGNMENT_MASK ( niEMAC_ALIGNMENT - 1U ) #else @@ -156,14 +157,17 @@ #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" #define niEMAC_AUTO_NEGOTIATION ipconfigENABLE -#define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#if ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) + #define niEMAC_USE_100MB ipconfigENABLE + #define niEMAC_USE_FULL_DUPLEX ipconfigENABLE +#endif + #define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) #define niEMAC_USE_RMII ipconfigENABLE -#define niEMAC_MAX_LINKED_TX_PACKETS 1 +#define niEMAC_BUFS_PER_DESC 2 /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ #define niEMAC_CRC_POLY 0x04C11DB7 @@ -422,14 +426,16 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; - ETH_HandleTypeDef * pxEthHandle = &xEthHandle; /* Zero-Copy Only */ configASSERT( xReleaseAfterSend == pdTRUE ); do { + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + if( ( pxDescriptor == NULL ) || ( pxDescriptor->pucEthernetBuffer == NULL ) || ( pxDescriptor->xDataLength > niEMAC_DATA_BUFFER_SIZE ) ) { + /* TODO: if xDataLength is greater than niEMAC_DATA_BUFFER_SIZE, you can use two buffers per descriptor */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Descriptor\n" ) ); break; } @@ -444,15 +450,15 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - if( ( xMacInitStatus != eMacInitComplete ) || ( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) ) + if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Interface Not Started\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); break; } - if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) + if( ( xMacInitStatus != eMacInitComplete ) || ( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) ) { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Interface Not Started\n" ) ); break; } @@ -474,50 +480,25 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N #endif }; + ETH_BufferTypeDef xTxBuffer = { + .buffer = pxDescriptor->pucEthernetBuffer, + .len = pxDescriptor->xDataLength, + .next = NULL + }; + xTxConfig.pData = pxDescriptor; - #if ipconfigIS_DISABLED( ipconfigUSE_LINKED_RX_MESSAGES ) - ETH_BufferTypeDef xTxBuffer = { - .buffer = ( uint8_t * ) pxDescriptor->pucEthernetBuffer, - .len = pxDescriptor->xDataLength, - .next = NULL - }; - - xTxConfig.TxBuffer = &xTxBuffer; - xTxConfig.Length = xTxBuffer.len; - - /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - if( niEMAC_CACHE_ENABLED ) - { - uint8_t * pucDataStart = xTxBuffer.buffer; - uint8_t * pucLineStart = ( uint8_t * ) ( ( uint32_t ) pucDataStart & ~niEMAC_ALIGNMENT_MASK ); - SCB_CleanDCache_by_Addr( ( uint32_t * ) pucLineStart, xTxBuffer.len + ( pucDataStart - pucLineStart ) ); - } - #endif*/ - #else - /* Support the possibility of linked Tx messages */ - ETH_BufferTypeDef xTxBuffer[ niEMAC_MAX_LINKED_TX_PACKETS ]; - - xTxConfig.TxBuffer = xTxBuffer; - xTxConfig.Length = 0; - UBaseType_t uxIndex = 0; - NetworkBufferDescriptor_t * pxCurDescriptor = pxDescriptor; - while( pxCurDescriptor != NULL ) + xTxConfig.TxBuffer = &xTxBuffer; + xTxConfig.Length = xTxBuffer.len; + + #ifdef niEMAC_CACHEABLE + if( niEMAC_CACHE_ENABLED ) { - ETH_BufferTypeDef * pxCurTxBuffer = &xTxBuffer[ uxIndex++ ]; - pxCurTxBuffer->buffer = ( uint8_t * ) pxCurDescriptor->pucEthernetBuffer; - pxCurTxBuffer->len = pxCurDescriptor->xDataLength; - pxCurTxBuffer->next = ( uxIndex < ARRAY_SIZE( xTxBuffer ) ) ? &xTxBuffer[ uxIndex ] : NULL; - xTxConfig.Length += pxCurTxBuffer->len; - /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - if( niEMAC_CACHE_ENABLED ) - { - uint8_t * pucDataStart = pxCurTxBuffer->buffer; - uint8_t * pucLineStart = ( uint8_t * ) ( ( uint32_t ) pucDataStart & ~niEMAC_ALIGNMENT_MASK ); - SCB_CleanDCache_by_Addr( ( uint32_t * ) pucLineStart, pxCurTxBuffer->len + ( pucDataStart - pucLineStart ) ); - } - #endif*/ - pxCurDescriptor = pxCurDescriptor->pxNextBuffer; - }; + const uintptr_t uxDataStart = ( uintptr_t ) xTxBuffer.buffer; + const uintptr_t uxLineStart = uxDataStart & ~niEMAC_ALIGNMENT_MASK; + const ptrdiff_t uxDataOffset = uxDataStart - uxLineStart; + const size_t uxLength = xTxBuffer.len + uxDataOffset; + SCB_CleanDCache_by_Addr( ( uint32_t * ) uxLineStart, uxLength ); + } #endif if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) @@ -911,6 +892,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo const NetworkEndPoint_t * const pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); if( pxEndPoint != NULL ) { + /* ipLOCAL_MAC_ADDRESS */ pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; #ifdef niEMAC_STM32FX @@ -1033,7 +1015,7 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface #if ipconfigIS_ENABLED( niEMAC_AUTO_CROSS ) .ucMDI_X = PHY_MDIX_AUTO, - #elif ( ipconfigIS_ENABLED( niEMAC_CROSSED_LINK ) ) + #elif ipconfigIS_ENABLED( niEMAC_CROSSED_LINK ) .ucMDI_X = PHY_MDIX_CROSSED, #else .ucMDI_X = PHY_MDIX_DIRECT, @@ -1248,6 +1230,12 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes BaseType_t xResult = pdFALSE; do { + if( pxDescriptor == NULL ) + { + FreeRTOS_debug_printf( ( "prvAcceptPacket: Null Descriptor\n" ) ); + break; + } + uint32_t ulErrorCode = 0; ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); if( ulErrorCode != 0 ) @@ -1445,12 +1433,12 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); - /*#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + #ifdef niEMAC_CACHEABLE if( niEMAC_CACHE_ENABLED ) { - SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pucBuff, usLength ); + SCB_InvalidateDCache_by_Addr( pucBuff, usLength ); } - #endif*/ + #endif } else { @@ -1512,6 +1500,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ + // niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) + // niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_ALIGNMENT_MASK ) & ~niEMAC_ALIGNMENT_MASK ) + return FreeRTOS_AddNetworkInterface( pxInterface ); } @@ -1683,48 +1674,54 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) #if 0 +#if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) + void MPU_Config(void) { - /* #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) */ - /* TODO: Usage based on if niEMAC_CACHE_ENABLED */ - - extern uint8_t __ETH_BUFFERS_START, __ETH_DESCRIPTORS_START; - - MPU_Region_InitTypeDef MPU_InitStruct; + MPU_Region_InitTypeDef MPU_InitStruct = {0}; HAL_MPU_Disable(); - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); + #ifdef defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + extern uint8_t __ETH_BUFFERS_START; + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + + extern uint8_t __ETH_DESCRIPTORS_START; + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + #endif /* if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } +#endif /* if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) */ + #endif /* if 0 */ /*---------------------------------------------------------------------------*/ From cd9024d44b581e7e1abae5d06fb4a6231e5d50b6 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 18 Jan 2024 09:48:06 -0500 Subject: [PATCH 42/68] fix cache size macro --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index fc057c8761..89a6ddec9a 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -137,7 +137,12 @@ #define niEMAC_CACHEABLE #define niEMAC_MPU_ENABLED ipconfigENABLE #define niEMAC_CACHE_ENABLED ( ipconfigIS_DISABLED( niEMAC_MPU_ENABLED ) && ( ( SCB->CCR & SCB_CCR_DC_Msk ) != 0 ) ) - #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE + #ifdef __SCB_DCACHE_LINE_SIZE + #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE + #else + /* _FLD2VAL( SCB_CCSIDR_LINESIZE, SCB->CCSIDR ) */ + #define niEMAC_ALIGNMENT 32U + #endif #define niEMAC_ALIGNMENT_MASK ( niEMAC_ALIGNMENT - 1U ) #else #define niEMAC_ALIGNMENT portBYTE_ALIGNMENT /* or should this always be 4? */ From 0da97774cc1a5701c518db338f90cb7bc8c267e9 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 18 Jan 2024 14:02:11 -0500 Subject: [PATCH 43/68] remove caching option --- .../NetworkInterface/STM32/NetworkInterface.c | 112 ++++++------------ 1 file changed, 39 insertions(+), 73 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 89a6ddec9a..264215f4fa 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -133,24 +133,13 @@ #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -#if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - #define niEMAC_CACHEABLE - #define niEMAC_MPU_ENABLED ipconfigENABLE - #define niEMAC_CACHE_ENABLED ( ipconfigIS_DISABLED( niEMAC_MPU_ENABLED ) && ( ( SCB->CCR & SCB_CCR_DC_Msk ) != 0 ) ) - #ifdef __SCB_DCACHE_LINE_SIZE - #define niEMAC_ALIGNMENT __SCB_DCACHE_LINE_SIZE - #else - /* _FLD2VAL( SCB_CCSIDR_LINESIZE, SCB->CCSIDR ) */ - #define niEMAC_ALIGNMENT 32U - #endif - #define niEMAC_ALIGNMENT_MASK ( niEMAC_ALIGNMENT - 1U ) -#else - #define niEMAC_ALIGNMENT portBYTE_ALIGNMENT /* or should this always be 4? */ - #define niEMAC_ALIGNMENT_MASK portBYTE_ALIGNMENT_MASK /* or should this always be 3? */ -#endif +#define niEMAC_DATA_ALIGNMENT 4 +#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1 ) +#define niEMAC_BUF_ALIGNMENT 32 +#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1 ) -#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_ALIGNMENT_MASK ) & ~niEMAC_ALIGNMENT_MASK ) +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) #define niEMAC_MAX_BLOCK_TIME_MS 100U #define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U @@ -495,17 +484,6 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.Length = xTxBuffer.len; - #ifdef niEMAC_CACHEABLE - if( niEMAC_CACHE_ENABLED ) - { - const uintptr_t uxDataStart = ( uintptr_t ) xTxBuffer.buffer; - const uintptr_t uxLineStart = uxDataStart & ~niEMAC_ALIGNMENT_MASK; - const ptrdiff_t uxDataOffset = uxDataStart - uxLineStart; - const size_t uxLength = xTxBuffer.len + uxDataOffset; - SCB_CleanDCache_by_Addr( ( uint32_t * ) uxLineStart, uxLength ); - } - #endif - if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) { /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ @@ -1437,13 +1415,6 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); - - #ifdef niEMAC_CACHEABLE - if( niEMAC_CACHE_ENABLED ) - { - SCB_InvalidateDCache_by_Addr( pucBuff, usLength ); - } - #endif } else { @@ -1469,7 +1440,7 @@ void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) { - static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_ALIGNMENT ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); + static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_BUF_ALIGNMENT ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); configASSERT( xBufferAllocFixedSize == pdTRUE ); @@ -1505,9 +1476,6 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ - // niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) - // niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_ALIGNMENT_MASK ) & ~niEMAC_ALIGNMENT_MASK ) - return FreeRTOS_AddNetworkInterface( pxInterface ); } @@ -1687,40 +1655,38 @@ void MPU_Config(void) HAL_MPU_Disable(); - #ifdef defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - extern uint8_t __ETH_BUFFERS_START; - - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - - extern uint8_t __ETH_DESCRIPTORS_START; - - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); - #endif /* if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) */ + extern uint8_t __ETH_BUFFERS_START; + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + + extern uint8_t __ETH_DESCRIPTORS_START; + + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } From 288cef225d5b3031576ec855712450aaf22a5983 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 21 Jan 2024 23:18:13 -0500 Subject: [PATCH 44/68] testing updates --- .../NetworkInterface/STM32/NetworkInterface.c | 1105 +++++++++++------ 1 file changed, 704 insertions(+), 401 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 264215f4fa..31da750d82 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -73,53 +73,7 @@ /*---------------------------------------------------------------------------*/ /*===========================================================================*/ -/* Config Checks */ -/*===========================================================================*/ -/*---------------------------------------------------------------------------*/ - -#if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) || ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning "Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM/ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface" - #endif -#endif - -#if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" - #endif -#endif - -/* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. - * So, don't use this macro, and filter anyways in the mean time. */ -/* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" - #endif -#endif */ - -#if ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning "Unsupported ipconfigNETWORK_MTU size" - #endif -#endif - -#if ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) - #error "Task Notifications must be enabled for NetworkInterface" -#endif - -#ifndef HAL_ETH_MODULE_ENABLED - #error "HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface" -#endif - -#if ( defined( STM32F4 ) || defined( STM32F7 ) ) && defined( ETH_RX_BUF_SIZE ) - #if ( niEMAC_DATA_BUFFER_SIZE != ETH_RX_BUF_SIZE ) - #warning "As of F7 V1.17.1 && F4 V1.28.0, a bug exists in the ETH HAL Driver where ETH_RX_BUF_SIZE is used instead of RxBuffLen, so ETH_RX_BUF_SIZE must == niEMAC_DATA_BUFFER_SIZE" - #endif -#endif - -/*---------------------------------------------------------------------------*/ -/*===========================================================================*/ -/* Macros */ +/* Config */ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ @@ -133,38 +87,121 @@ #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -#define niEMAC_DATA_ALIGNMENT 4 -#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1 ) -#define niEMAC_BUF_ALIGNMENT 32 -#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1 ) +#define niEMAC_DATA_ALIGNMENT 4U +#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) +#define niEMAC_BUF_ALIGNMENT 32U +#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1U ) #define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) #define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) -#define niEMAC_MAX_BLOCK_TIME_MS 100U -#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 200U +#define niEMAC_TASK_MAX_BLOCK_TIME_MS 100U +#define niEMAC_TX_MAX_BLOCK_TIME_MS 20U +#define niEMAC_RX_MAX_BLOCK_TIME_MS 20U +#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 20U #define niEMAC_TASK_NAME "EMAC_STM32" #define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) #define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" +#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" #define niEMAC_AUTO_NEGOTIATION ipconfigENABLE -#if ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) - #define niEMAC_USE_100MB ipconfigENABLE - #define niEMAC_USE_FULL_DUPLEX ipconfigENABLE -#endif +#define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) #define niEMAC_USE_RMII ipconfigENABLE -#define niEMAC_BUFS_PER_DESC 2 +#ifdef niEMAC_STM32HX + #define niEMAC_AUTO_LOW_POWER ( ipconfigDISABLE && ipconfigIS_DISABLED( niEMAC_USE_RMII ) ) +#endif -/* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ -#define niEMAC_CRC_POLY 0x04C11DB7 +/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* Config Checks */ +/*===========================================================================*/ +/*---------------------------------------------------------------------------*/ + +#ifndef HAL_ETH_MODULE_ENABLED + #error "HAL_ETH_MODULE_ENABLED must be enabled for NetworkInterface" +#endif + +#if ipconfigIS_DISABLED( configUSE_TASK_NOTIFICATIONS ) + #error "Task Notifications must be enabled for NetworkInterface" +#endif + +#if ipconfigIS_DISABLED( ipconfigZERO_COPY_TX_DRIVER ) + #error "ipconfigZERO_COPY_TX_DRIVER must be enabled for NetworkInterface" +#endif + +#if ipconfigIS_DISABLED( ipconfigZERO_COPY_RX_DRIVER ) + #error "ipconfigZERO_COPY_RX_DRIVER must be enabled for NetworkInterface" +#endif + +#if ( ipconfigNETWORK_MTU < ETH_MIN_PAYLOAD ) || ( ipconfigNETWORK_MTU > ETH_MAX_PAYLOAD ) + #error "Unsupported ipconfigNETWORK_MTU size for NetworkInterface" +#endif + +#if defined( niEMAC_STM32HX ) + + #if ( ETH_TX_DESC_CNT % 4 != 0 ) + #error "Invalid ETH_TX_DESC_CNT value for NetworkInterface, must be a multiple of 4" + #endif + + #if ( ETH_RX_DESC_CNT % 4 != 0 ) + #error "Invalid ETH_RX_DESC_CNT value for NetworkInterface, must be a multiple of 4" + #endif + +#elif defined( niEMAC_STM32FX ) + + #if defined( ETH_RX_BUF_SIZE ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) + /* __STM32F7xx_HAL_VERSION, __STM32F4xx_HAL_VERSION */ + #warning "As of F7 V1.17.1 && F4 V1.28.0, a bug exists in the ETH HAL Driver where ETH_RX_BUF_SIZE is used instead of RxBuffLen, so ETH_RX_BUF_SIZE must == niEMAC_DATA_BUFFER_SIZE" + #endif + #endif + +#endif + +#if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) + + #if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + #warning "Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM for NetworkInterface" + #endif + + #if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) + #warning "Consider enabling ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM for NetworkInterface" + #endif + + #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" + #endif + + #if ipconfigIS_DISABLED( ipconfigUSE_LINKED_RX_MESSAGES ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" + #endif + +#endif + +/* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. + * So, don't use this macro, and filter anyways in the mean time. */ +/* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" + #endif +#endif */ + +/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* Macros & Definitions */ +/*===========================================================================*/ +/*---------------------------------------------------------------------------*/ + +#define niEMAC_BUFS_PER_DESC 2U /* TODO: Enabled and use interrupts for phy instead of polling? */ /*#define niPHY_ISR_AN_COMPLETE 0x0040 @@ -173,7 +210,14 @@ #define niPHY_IMR_AN_COMPLETE 0x0040 #define niPHY_IMR_LINK_DOWN 0x0010*/ -#define niEMAC_MAC_IS_MULTICAST( pucMacAddress ) ( ( pucMacAddress[ 0 ] & 1U ) != 0 ) +/* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ +#define niEMAC_CRC_POLY 0x04C11DB7 +#define niEMAC_MAC_IS_MULTICAST( MAC ) ( ( MAC[ 0 ] & 1U ) != 0 ) +#define niEMAC_MAC_IS_UNICAST( MAC ) ( ( MAC[ 0 ] & 1U ) == 0 ) +#define niEMAC_ADDRESS_HASH_BITS 64U +#define niEMAC_MAC_SRC_MATCH_COUNT 3U + +#define niEMAC_DEBUG( X, MSG ) if( ( X ) != 0 ) { FreeRTOS_debug_printf( ( MSG ) ); } /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -183,6 +227,7 @@ /* Interrupt events to process: reception, transmission and error handling. */ typedef enum { + eMacEventNone = 0, eMacEventRx = 1 << 0, eMacEventTx = 1 << 1, eMacEventErrRx = 1 << 2, @@ -233,7 +278,7 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); -//static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); /* EMAC Task */ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); @@ -246,9 +291,9 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkI static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); /* EMAC Helpers */ +static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ); static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); static uint32_t prvCalcCrc32( const uint8_t * pucMAC ); -static void prvUpdateMacHashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ); static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ); static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ); @@ -271,21 +316,29 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net static ETH_HandleTypeDef xEthHandle; +/* static ETH_TxPacketConfig xTxConfig; */ + static EthernetPhy_t xPhyObject; -static TaskHandle_t xEMACTaskHandle; +static TaskHandle_t xEMACTaskHandle = NULL; -static SemaphoreHandle_t xTxMutex; +static SemaphoreHandle_t xTxMutex = NULL, xTxDescSem = NULL; -static BaseType_t xSwitchRequired; +static BaseType_t xSwitchRequired = pdFALSE; static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; -/* Store previously matched addresses for easy checking */ -static MACAddress_t xMatchedMacAddresses[ 3 ] = { 0 }; - +/* Src Mac Matching */ /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ -static UBaseType_t uxMACEntry = ETH_MAC_ADDRESS1; +/* TODO: Stil need to check if new address matches ETH_MAC_ADDRESS0 */ +static const uint32_t xMacAddressEntries[ niEMAC_MAC_SRC_MATCH_COUNT ] = { ETH_MAC_ADDRESS1, ETH_MAC_ADDRESS2, ETH_MAC_ADDRESS3 }; +static MACAddress_t xMatchedMacAddresses[ niEMAC_MAC_SRC_MATCH_COUNT ]; +static uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ] = { 0U }; +static uint8_t uxMACEntryIndex = 0; + +/* Src Mac Hashing */ +static uint32_t ulHashTable[ niEMAC_ADDRESS_HASH_BITS / 32 ]; +static uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ] = { 0U }; /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -331,7 +384,7 @@ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ) BaseType_t xReturn = pdFALSE; - /* const BaseType_t xEMACIndex = *( ( BaseType_t * ) pxInterface->pvArgument ); */ + /* const EMACData_t xEMACData = *( ( EMACData_t * ) pxInterface->pvArgument ); */ if( xPhyObject.ulLinkStatusMask != 0U ) { @@ -358,6 +411,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac case eMacEthInit: if( prvEthConfigInit( pxEthHandle, pxInterface ) == pdFALSE ) { + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacEthInit failed\n" ) ); break; } @@ -369,6 +423,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac if( xPhyDiscover( pxPhyObject ) == 0 ) { + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyInit failed\n" ) ); break; } @@ -378,6 +433,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac case eMacPhyStart: if( prvPhyStart( pxEthHandle, pxInterface, pxPhyObject ) == pdFALSE ) { + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyStart failed\n" ) ); break; } @@ -387,6 +443,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac case eMacTaskStart: if( prvEMACTaskStart( pxInterface ) == pdFALSE ) { + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacTaskStart failed\n" ) ); break; } @@ -394,10 +451,11 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacEthStart: - if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) + if( HAL_ETH_GetState( pxEthHandle ) != HAL_ETH_STATE_STARTED ) { if( HAL_ETH_Start_IT( pxEthHandle ) != HAL_OK ) { + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacEthStart failed\n" ) ); break; } } @@ -406,10 +464,13 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacInitComplete: - if( prvGetPhyLinkStatus( pxInterface ) == pdTRUE ) + if( prvGetPhyLinkStatus( pxInterface ) != pdTRUE ) { - xInitResult = pdPASS; + FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacInitComplete failed\n" ) ); + break; } + + xInitResult = pdPASS; } return xInitResult; @@ -429,7 +490,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N if( ( pxDescriptor == NULL ) || ( pxDescriptor->pucEthernetBuffer == NULL ) || ( pxDescriptor->xDataLength > niEMAC_DATA_BUFFER_SIZE ) ) { - /* TODO: if xDataLength is greater than niEMAC_DATA_BUFFER_SIZE, you can use two buffers per descriptor */ + /* TODO: if xDataLength is greater than niEMAC_DATA_BUFFER_SIZE, you can link buffers */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Invalid Descriptor\n" ) ); break; } @@ -450,30 +511,107 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - if( ( xMacInitStatus != eMacInitComplete ) || ( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) ) + if( ( xMacInitStatus != eMacInitComplete ) || ( HAL_ETH_GetState( pxEthHandle ) != HAL_ETH_STATE_STARTED ) ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Interface Not Started\n" ) ); break; } - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); + break; + } + + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_TX_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); + ( void ) xSemaphoreGive( xTxDescSem ); /* TODO: Can we queue it? */ break; } + /* static ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ] = { 0 }; */ + static ETH_TxPacketConfig xTxConfig = { + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, + .Length = 0U, + .TxBuffer = NULL, + .SrcAddrCtrl = ETH_SRC_ADDR_CONTROL_DISABLE, .CRCPadCtrl = ETH_CRC_PAD_INSERT, - #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD | ETH_TX_PACKETS_FEATURES_CSUM, - .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, - #else - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, - .ChecksumCtrl = ETH_CHECKSUM_DISABLE, - #endif + .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, + .MaxSegmentSize = ipconfigTCP_MSS, + .PayloadLen = 0U, + .TCPHeaderLen = 0U, + .VlanTag = 0U, + .VlanCtrl = ETH_VLAN_DISABLE, + .InnerVlanTag = 0U, + .InnerVlanCtrl = ETH_INNER_VLAN_DISABLE, + .pData = NULL, }; + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; + #endif + + #if 0 + + const EthernetHeader_t * const pxEthHeader = ( const EthernetHeader_t * const ) pxDescriptor->pucEthernetBuffer; + + if( pxEthHeader->usFrameType == ipIPv4_FRAME_TYPE ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + const IPPacket_t * const pxIPPacket = ( const IPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + + if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) + { + ICMPPacket_t * const pxICMPPacket = ( ICMPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + pxICMPPacket->xICMPHeader.usChecksum = 0U; + #endif + } + else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_TCP ) + { + TCPPacket_t * const pxTCPPacket = ( TCPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) /* && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) */ + /* pxTCPSocketLookup */ + xTxConfig.PayloadLen = pxTCPPacket->xIPHeader.usLength; + xTxConfig.TCPHeaderLen = ( ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ) * 4U ); + xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; + #endif + } + #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + } + else if( pxEthHeader->usFrameType == ipIPv6_FRAME_TYPE ) + { + /* #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ + const IPPacket_IPv6_t * pxIPPacket_IPv6 = ( IPPacket_IPv6_t * ) pxDescriptor->pucEthernetBuffer; + + if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_ICMP_IPv6 ) + { + ICMPPacket_IPv6_t * const pxICMPPacket_IPv6 = ( ICMPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + pxICMPPacket_IPv6->xICMPHeaderIPv6.usChecksum = 0U; + #endif + } + else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_TCP ) + { + TCPPacket_IPv6_t * const pxTCPPacket_IPv6 = ( TCPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) /* && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) */ + xTxConfig.PayloadLen = pxTCPPacket_IPv6->xIPHeader.usPayloadLength; + xTxConfig.TCPHeaderLen = sizeof( pxTCPPacket_IPv6->xTCPHeader ); + xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; + #endif + } + /* #endif */ /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ + } + else if( pxEthHeader->usFrameType == ipARP_FRAME_TYPE ) + { + + } + + #endif + ETH_BufferTypeDef xTxBuffer = { .buffer = pxDescriptor->pucEthernetBuffer, .len = pxDescriptor->xDataLength, @@ -492,12 +630,10 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N } else { - configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); - if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Tx Busy\n" ) ); - } + ( void ) xSemaphoreGive( xTxDescSem ); + configASSERT( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ); + niEMAC_DEBUG( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_BUSY ) != 0, "xNetworkInterfaceOutput: Tx Busy\n" ); + /* Add to queue? */ } ( void ) xSemaphoreGive( xTxMutex ); @@ -515,112 +651,130 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { - configASSERT( pucMacAddress ); - - BaseType_t xFound = pdFALSE; - for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) + BaseType_t xFoundMatch = pdFALSE; + for( UBaseType_t uxIndex = 0; uxIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++uxIndex ) { - /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ - if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + if( ucSrcMatchCounters[ uxIndex ] > 0U ) { - /* Already assigned this mac address */ - xFound = pdTRUE; + /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ + if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + /* Already assigned this mac address */ + ++( ucSrcMatchCounters[ uxIndex ] ); + xFoundMatch = pdTRUE; + break; + } + } + else + { + if( uxMACEntryIndex > niEMAC_MAC_SRC_MATCH_COUNT ) + { + uxMACEntryIndex = niEMAC_MAC_SRC_MATCH_COUNT; + } } } - if( xFound == pdFALSE ) + if( xFoundMatch == pdFALSE ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; - ETH_MACFilterConfigTypeDef xFilterConfig; - switch( uxMACEntry ) - { - case ETH_MAC_ADDRESS1: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); - ( void ) memcpy( xMatchedMacAddresses[ 0 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); - uxMACEntry = ETH_MAC_ADDRESS2; - /* Only need to do this once, don't repeat for following addresses */ - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - if( xFilterConfig.HachOrPerfectFilter == DISABLE ) - { - xFilterConfig.HachOrPerfectFilter = ENABLE; - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - } - break; - - case ETH_MAC_ADDRESS2: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); - ( void ) memcpy( xMatchedMacAddresses[ 1 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); - uxMACEntry = ETH_MAC_ADDRESS3; - break; + const uint32_t ulHash = prvCalcCrc32( pucMacAddress ); + const uint8_t ucHashIndex = ( ulHash >> 26 ) & 0x3FU; - case ETH_MAC_ADDRESS3: - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, uxMACEntry, ( uint8_t * ) pucMacAddress ); - ( void ) memcpy( xMatchedMacAddresses[ 2 ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); - /* Just used to show that the address registers are filled */ - uxMACEntry = ETH_MAC_ADDRESS0; - break; + if( uxMACEntryIndex < niEMAC_MAC_SRC_MATCH_COUNT ) + { + if( ucAddrHashCounters[ ucHashIndex ] == 0U ) + { + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, xMacAddressEntries[ uxMACEntryIndex ], ( uint8_t * ) pucMacAddress ); + ( void ) memcpy( xMatchedMacAddresses[ uxMACEntryIndex ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); + ucSrcMatchCounters[ uxMACEntryIndex ] = 1U; + xFoundMatch = pdTRUE; + } + } - case ETH_MAC_ADDRESS0: - prvUpdateMacHashFilter( pxEthHandle, pucMacAddress ); - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - if( niEMAC_MAC_IS_MULTICAST( pucMacAddress ) == pdTRUE ) + if( xFoundMatch == pdFALSE ) + { + if( ucAddrHashCounters[ ucHashIndex ] == 0 ) + { + if( ucHashIndex & 0x20U ) { - if( xFilterConfig.HashMulticast == DISABLE ) - { - xFilterConfig.HashMulticast = ENABLE; - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - } + ulHashTable[ 1 ] |= ( 1U << ( ucHashIndex & 0x1FU ) ); } else { - if( xFilterConfig.HashUnicast == DISABLE ) - { - xFilterConfig.HashUnicast = ENABLE; - ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - } + ulHashTable[ 0 ] |= ( 1U << ucHashIndex ); } - break; - default: - configASSERT( pdFALSE ); - break; + ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + } + + if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) + { + ++( ucAddrHashCounters[ ucHashIndex ] ); + } } } } /*---------------------------------------------------------------------------*/ -#if 0 - static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { - configASSERT( pucMacAddress ); - - /* const BaseType_t xIsMulticast = niEMAC_MAC_IS_MULTICAST( pucMacAddress ); */ - - BaseType_t xFound = pdFALSE; - for( UBaseType_t uxIndex = 0; uxIndex < ARRAY_SIZE( xMatchedMacAddresses ); ++uxIndex ) + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + BaseType_t xFoundMatch = pdFALSE; + for( UBaseType_t uxIndex = 0; uxIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++uxIndex ) { - /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ - if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + if( ucSrcMatchCounters[ uxIndex ] > 0U ) { - /* Already assigned this mac address */ - xFound = pdTRUE; + /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ + if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) + { + if( ucSrcMatchCounters[ uxIndex ] < UINT8_MAX ) + { + --( ucSrcMatchCounters[ uxIndex ] ); + + if( ucSrcMatchCounters[ uxIndex ] == 0 ) + { + /* TODO: Just disable it, don't need to clear? */ + ( void ) memset( &( xMatchedMacAddresses[ uxIndex ].ucBytes ), 0, ipMAC_ADDRESS_LENGTH_BYTES ); + ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, xMacAddressEntries[ uxIndex ], xMatchedMacAddresses[ uxIndex ].ucBytes ); + } + } + xFoundMatch = pdTRUE; + break; + } } } - if( xFound == pdTRUE ) + if( xFoundMatch == pdFALSE ) { - ETH_HandleTypeDef * pxEthHandle = &xEthHandle; - ETH_MACFilterConfigTypeDef xFilterConfig; - ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); + const uint32_t ulHash = prvCalcCrc32( pucMacAddress ); + const uint8_t ucHashIndex = ( ulHash >> 26 ) & 0x3FU; + + if( ucAddrHashCounters[ ucHashIndex ] > 0U ) + { + if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) + { + --( ucAddrHashCounters[ ucHashIndex ] ); + if( ucAddrHashCounters[ ucHashIndex ] == 0 ) + { + if( ucHashIndex & 0x20U ) + { + ulHashTable[ 1 ] &= ~( 1U << ( ucHashIndex & 0x1FU ) ); + } + else + { + ulHashTable[ 0 ] &= ~( 1U << ucHashIndex ); + } + + ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + } + } + } } } -#endif - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* EMAC Task */ @@ -631,38 +785,39 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net { BaseType_t xResult = pdFALSE; UBaseType_t uxCount = 0; - /* if( ( xMacInitStatus == eMacInitComplete ) && ( heth->gState == HAL_ETH_STATE_STARTED ) ) */ #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; - - while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) + if( ( xMacInitStatus == eMacInitComplete ) && ( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ) ) { - ++uxCount; - if( pxCurDescriptor == NULL ) + while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { - /* Buffer was dropped, ignore packet */ - continue; - } - configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); - - pxCurDescriptor->pxInterface = pxInterface; - pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); - #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) - if( pxStartDescriptor == NULL ) - { - pxStartDescriptor = pxCurDescriptor; - } - else if( pxEndDescriptor != NULL ) + ++uxCount; + if( pxCurDescriptor == NULL ) { - pxEndDescriptor->pxNextBuffer = pxCurDescriptor; + /* Buffer was dropped, ignore packet */ + continue; } - pxEndDescriptor = pxCurDescriptor; - #else - prvSendRxEvent( pxCurDescriptor ); - #endif + configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); + + pxCurDescriptor->pxInterface = pxInterface; + pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) + if( pxStartDescriptor == NULL ) + { + pxStartDescriptor = pxCurDescriptor; + } + else if( pxEndDescriptor != NULL ) + { + pxEndDescriptor->pxNextBuffer = pxCurDescriptor; + } + pxEndDescriptor = pxCurDescriptor; + #else + prvSendRxEvent( pxCurDescriptor ); + #endif + } } if( uxCount > 0 ) @@ -672,15 +827,6 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net #endif xResult = pdTRUE; } - else - { - configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); - /*if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) - { - ( void ) xTaskNotify( xEMACTaskHandle, eMacEventErrEth, eSetBits ); - }*/ - xResult = pdFALSE; - } return xResult; } @@ -690,7 +836,6 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { NetworkInterface_t * pxInterface = ( NetworkInterface_t * ) pvParameters; - configASSERT( pxInterface ); ETH_HandleTypeDef * pxEthHandle = &xEthHandle; EthernetPhy_t * pxPhyObject = &xPhyObject; @@ -701,7 +846,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) BaseType_t xResult = pdFALSE; uint32_t ulISREvents = 0U; - if( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) == pdTRUE ) + if( xTaskNotifyWait( 0U, eMacEventAll, &ulISREvents, pdMS_TO_TICKS( niEMAC_TASK_MAX_BLOCK_TIME_MS ) ) == pdTRUE ) { if( ( ulISREvents & eMacEventRx ) != 0 ) { @@ -710,63 +855,47 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventTx ) != 0 ) { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) - { - ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); - ( void ) xSemaphoreGive( xTxMutex ); - } + prvReleaseTxPacket( pxEthHandle ); } if( ( ulISREvents & eMacEventErrRx ) != 0 ) { - /*do - { - xResult = ( prvNetworkInterfaceInput() > 0 ); - } while ( xResult != pdFALSE ); - xResult = pdTRUE;*/ + xResult = prvNetworkInterfaceInput( pxEthHandle, pxInterface ); } if( ( ulISREvents & eMacEventErrTx ) != 0 ) { - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) - { - ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); - } + prvReleaseTxPacket( pxEthHandle ); } if( ( ulISREvents & eMacEventErrEth ) != 0 ) { - /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ - /* configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); */ - } - - if( ( ulISREvents & eMacEventErrMac ) != 0 ) - { - /* pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC */ - /* pxEthHandle->MACErrorCode */ + configASSERT( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_PARAM ) == 0 ); + if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) + { + /* Recover from critical error */ + ( void ) HAL_ETH_Init( pxEthHandle ); + ( void ) HAL_ETH_Start_IT( pxEthHandle ); + xResult = prvNetworkInterfaceInput( pxEthHandle, pxInterface ); + } } - if( ( ulISREvents & eMacEventErrDma ) != 0 ) - { - /* pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA */ - /* pxEthHandle->DMAErrorCode */ - } + /* if( ( ulISREvents & eMacEventErrMac ) != 0 ) */ + /* if( ( ulISREvents & eMacEventErrDma ) != 0 ) */ } - /* #ifdef niEMAC_STM32HX - prvUpdatePacketFilter( pxEthHandle, pxInterface ); - #endif */ - - /* pxEthHandle->gState == HAL_ETH_STATE_ERROR */ - /* configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); */ - if( xPhyCheckLinkStatus( pxPhyObject, xResult ) != pdFALSE ) { if( prvGetPhyLinkStatus( pxInterface ) != pdFALSE ) { - if( pxEthHandle->gState == HAL_ETH_STATE_READY ) + if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) { - /* Link Was Down */ + /* Recover from critical error */ + ( void ) HAL_ETH_Init( pxEthHandle ); + } + if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_READY ) + { + /* Link was down or critical error occurred */ if( prvMacUpdateConfig( pxEthHandle, pxPhyObject ) != pdFALSE ) { ( void ) HAL_ETH_Start_IT( pxEthHandle ); @@ -776,9 +905,8 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) else { ( void ) HAL_ETH_Stop_IT( pxEthHandle ); + prvReleaseTxPacket( pxEthHandle ); #if ( ipconfigIS_ENABLED( ipconfigSUPPORT_NETWORK_DOWN_EVENT ) ) - /* ( void ) HAL_ETH_DeInit( pxEthHandle ); - xMacInitStatus = eMacEthInit; */ FreeRTOS_NetworkDown( pxInterface ); #endif } @@ -804,7 +932,26 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); } - if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) ) + if( xTxDescSem == NULL ) + { + #if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) + static StaticSemaphore_t xTxDescSemBuf; + xTxDescSem = xSemaphoreCreateCountingStatic( + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT, + &xTxDescSemBuf + ); + #else + xTxDescSem = xSemaphoreCreateCounting( + ( UBaseType_t ) ETH_TX_DESC_CNT, + ( UBaseType_t ) ETH_TX_DESC_CNT + ); + #endif + configASSERT( xTxDescSem != NULL ); + vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); + } + + if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) { #if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; @@ -850,11 +997,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo pxEthHandle->Instance = ETH; - #if ipconfigIS_ENABLED( niEMAC_USE_RMII ) - pxEthHandle->Init.MediaInterface = HAL_ETH_RMII_MODE; - #else - pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE; - #endif + pxEthHandle->Init.MediaInterface = ipconfigIS_ENABLED( niEMAC_USE_RMII ) ? HAL_ETH_RMII_MODE : HAL_ETH_MII_MODE; pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); @@ -863,12 +1006,14 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo configASSERT( pxEthHandle->Init.RxBuffLen == ETH_RX_BUF_SIZE ); #endif + #ifdef niEMAC_STM32HX + configASSERT( ETH_TX_DESC_CNT % 4 == 0 ); + configASSERT( ETH_RX_DESC_CNT % 4 == 0 ); + #endif static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); - pxEthHandle->Init.TxDesc = xDMADescTx; pxEthHandle->Init.RxDesc = xDMADescRx; - ( void ) memset( &xDMADescTx, 0, sizeof( xDMADescTx ) ); ( void ) memset( &xDMADescRx, 0, sizeof( xDMADescRx ) ); @@ -878,25 +1023,52 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo /* ipLOCAL_MAC_ADDRESS */ pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; - #ifdef niEMAC_STM32FX + #if defined( niEMAC_STM32FX ) /* This function doesn't get called in Fxx driver */ HAL_ETH_SetMDIOClockRange( pxEthHandle ); #endif if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) { - /* ETH_DMAConfigTypeDef xDMAConfig; - xDMAConfig.SecondPacketOperate = ENABLE; - ( void ) HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ); */ - - /* #ifdef niEMAC_STM32HX - HAL_ETHEx_DisableARPOffload( pxEthHandle ); - HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); - HAL_ETHEx_EnableARPOffload( pxEthHandle ); + /* xTxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; + xTxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD; + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + #else + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_DISABLE; #endif */ - #ifdef niEMAC_STM32HX + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); + #if defined( niEMAC_STM32FX ) + xMACConfig.AutomaticPadCRCStrip = ENABLE; + xMACConfig.RetryTransmission = ENABLE; + #elif defined( niEMAC_STM32HX ) + xMACConfig.CRCStripTypePacket = DISABLE; + #endif + ( void ) HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ); + + ETH_DMAConfigTypeDef xDMAConfig; + ( void ) HAL_ETH_GetDMAConfig( pxEthHandle, &xDMAConfig ); + #if defined( niEMAC_STM32FX ) + xDMAConfig.EnhancedDescriptorFormat = ( FunctionalState ) ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) || ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ); + #elif defined( niEMAC_STM32HX ) + xDMAConfig.SecondPacketOperate = ENABLE; + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) + xDMAConfig.TCPSegmentation = ENABLE; + xDMAConfig.MaximumSegmentSize = ipconfigTCP_MSS; + #endif + #endif + ( void ) HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ); + + #if defined( niEMAC_STM32HX ) prvInitPacketFilter( pxEthHandle, pxInterface ); + + /* HAL_ETHEx_DisableARPOffload( pxEthHandle ); + HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); + HAL_ETHEx_EnableARPOffload( pxEthHandle ); */ #endif prvInitMacAddresses( pxEthHandle, pxInterface ); @@ -907,19 +1079,44 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo if( xResult == pdTRUE ) { - configASSERT( NVIC_GetEnableIRQ( ETH_IRQn ) != 0 ); + #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + if( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) + { + #if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) + configASSERT( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ); + #else + configASSERT( pdFALSE ); + #endif + } + #endif + uint32_t ulPreemptPriority, ulSubPriority; HAL_NVIC_GetPriority( ETH_IRQn, HAL_NVIC_GetPriorityGrouping(), &ulPreemptPriority, &ulSubPriority ); - configASSERT( ulPreemptPriority >= configMAX_FREERTOS_INTERRUPT_PRIORITY ); if( ulPreemptPriority < configMAX_FREERTOS_INTERRUPT_PRIORITY ) { + FreeRTOS_debug_printf( ( "prvEthConfigInit: Incorrectly set ETH_IRQn priority\n" ) ); HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_FREERTOS_INTERRUPT_PRIORITY, 0 ); } if( NVIC_GetEnableIRQ( ETH_IRQn ) == 0 ) { + FreeRTOS_debug_printf( ( "prvEthConfigInit: ETH_IRQn was not enabled by application\n" ) ); HAL_NVIC_EnableIRQ( ETH_IRQn ); } } + else + { + #ifdef niEMAC_STM32FX + configASSERT( __HAL_RCC_ETH_IS_CLK_ENABLED() != 0 ); + #elif defined( STM32H5 ) + configASSERT( __HAL_RCC_ETH_IS_CLK_ENABLED() != 0 ); + configASSERT( __HAL_RCC_ETHTX_IS_CLK_ENABLED() != 0 ); + configASSERT( __HAL_RCC_ETHRX_IS_CLK_ENABLED() != 0 ); + #elif defined( STM32H7) + configASSERT( __HAL_RCC_ETH1MAC_IS_CLK_ENABLED() != 0 ); + configASSERT( __HAL_RCC_ETH1TX_IS_CLK_ENABLED() != 0 ); + configASSERT( __HAL_RCC_ETH1RX_IS_CLK_ENABLED() != 0 ); + #endif + } return xResult; } @@ -930,28 +1127,22 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkI { ETH_MACFilterConfigTypeDef xFilterConfig; ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); - - /* These are always constant */ - xFilterConfig.PromiscuousMode = DISABLE; xFilterConfig.ReceiveAllMode = DISABLE; - xFilterConfig.PassAllMulticast = DISABLE; - xFilterConfig.BroadcastFilter = ENABLE; + xFilterConfig.HachOrPerfectFilter = ENABLE; xFilterConfig.SrcAddrFiltering = DISABLE; xFilterConfig.SrcAddrInverseFiltering = DISABLE; - xFilterConfig.DestAddrInverseFiltering = DISABLE; #ifdef niEMAC_STM32FX /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ xFilterConfig.ControlPacketsFilter = ETH_MACFFR_PCF_BlockAll; #else xFilterConfig.ControlPacketsFilter = ETH_CTRLPACKETS_BLOCK_ALL; #endif - - /* These are determined later in prvAddAllowedMACAddress, just set default disable */ - xFilterConfig.HachOrPerfectFilter = DISABLE; - xFilterConfig.HashUnicast = DISABLE; - xFilterConfig.HashMulticast = DISABLE; - - /* Update the initial configuration, it may be changed again in prvAddAllowedMACAddress */ + xFilterConfig.BroadcastFilter = ENABLE; + xFilterConfig.PassAllMulticast = DISABLE; + xFilterConfig.DestAddrInverseFiltering = DISABLE; + xFilterConfig.HashMulticast = ENABLE; + xFilterConfig.HashUnicast = ENABLE; + xFilterConfig.PromiscuousMode = DISABLE; ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) @@ -1005,6 +1196,11 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface #endif }; + #if ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) + pxPhyObject->xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; + pxPhyObject->xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + #endif + if( xPhyConfigure( pxPhyObject, &xPhyProperties ) == 0 ) { if( prvMacUpdateConfig( pxEthHandle, pxPhyObject ) != pdFALSE ) @@ -1027,39 +1223,57 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface /*===========================================================================*/ /*---------------------------------------------------------------------------*/ +static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ) +{ + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_TX_MAX_BLOCK_TIME_MS ) ) != pdFALSE ) + { + ( void ) HAL_ETH_ReleaseTxPacket( pxEthHandle ); + ( void ) xSemaphoreGive( xTxMutex ); + } + else + { + FreeRTOS_debug_printf( ( "prvReleaseTxPacket: Failed\n" ) ); + } + + /* TODO: Is it possible for the semaphore and BuffersInUse to get out of sync? */ + /* while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > pxEthHandle->TxDescList.BuffersInUse ) + { + ( void ) xSemaphoreGive( xTxDescSem ); + } */ +} + static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; - if( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) + if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ) { ( void ) HAL_ETH_Stop_IT( pxEthHandle ); } ETH_MACConfigTypeDef xMACConfig; ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); #if ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) - /* TODO: xPhyStartAutoNegotiation always returns 0, Should return -1 if xPhyGetMask == 0 ? */ ( void ) xPhyStartAutoNegotiation( pxPhyObject, xPhyGetMask( pxPhyObject ) ); - xMACConfig.DuplexMode = ( pxPhyObject->xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; - xMACConfig.Speed = ( pxPhyObject->xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; #else - pxPhyObject->xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; - pxPhyObject->xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; - /* ucMDI_X unused */ - /* TODO: xPhyFixedValue always return 0 */ ( void ) xPhyFixedValue( pxPhyObject, xPhyGetMask( pxPhyObject ) ); - xMACConfig.DuplexMode = pxPhyObject->xPhyPreferences.ucDuplex; - xMACConfig.Speed = pxPhyObject->xPhyPreferences.ucSpeed; #endif + xMACConfig.DuplexMode = ( pxPhyObject->xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) ? ETH_FULLDUPLEX_MODE : ETH_HALFDUPLEX_MODE; + xMACConfig.Speed = ( pxPhyObject->xPhyProperties.ucSpeed == PHY_SPEED_10 ) ? ETH_SPEED_10M : ETH_SPEED_100M; if( HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ) == HAL_OK ) { xResult = pdTRUE; } + #if ipconfigIS_ENABLED( niEMAC_AUTO_LOW_POWER ) + if( ( pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE ) && ( xMACConfig.DuplexMode == ETH_FULLDUPLEX_MODE ) && ( xMACConfig.Speed == ETH_SPEED_100M ) ) + { + HAL_ETHEx_EnterLPIMode( pxEthHandle, ENABLE, DISABLE ); + } + #endif + return xResult; } @@ -1068,52 +1282,27 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP /* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ static uint32_t prvCalcCrc32( const uint8_t * pucMAC ) { - uint32_t ulCRC32 = 0xFFFFFFFF; + uint32_t ulCRC32 = 0xFFFFFFFFU; - for( uint8_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) + for( uint32_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) { - ulCRC32 ^= ( uint32_t ) pucMAC[ ucIndex ]; + ulCRC32 ^= __RBIT( pucMAC[ ipMAC_ADDRESS_LENGTH_BYTES - ucIndex ] ); - for( uint8_t ucJndex = 0; ucJndex < 8; ++ucJndex ) + for( uint8_t ucJndex = 8; ucJndex > 0; --ucJndex ) { - const BaseType_t xTemp = ulCRC32 & 1; - ulCRC32 >>= 1; - if( xTemp ) + if( ulCRC32 & 0x80000000U ) { - ulCRC32 ^= __RBIT( niEMAC_CRC_POLY ); + ulCRC32 <<= 1; + ulCRC32 ^= niEMAC_CRC_POLY; + } + else + { + ulCRC32 <<= 1; } } } - /* Perform bitwise reversal on the CRC32 */ - return __RBIT( ~ulCRC32 ); -} - -/*---------------------------------------------------------------------------*/ - -/* Update the Hash Table Registers with hash value of the given MAC address */ -static void prvUpdateMacHashFilter( ETH_HandleTypeDef * pxEthHandle, const uint8_t * pucMAC ) -{ - static uint32_t ulHashTable[ 2 ]; - - /* Calculate the 32-bit CRC for the MAC */ - const uint32_t ulHash = prvCalcCrc32( pucMAC ); - - /* Take the upper 6 bits of the above result */ - const uint8_t ucEntry = ( ulHash >> 26 ) & 0x3F; - - /* Use the upper or lower Hash Table Registers - * to set the required bit based on the ulHash */ - if( ucEntry < 32 ) - { - ulHashTable[ 0 ] |= ( 1 << ucEntry ); - } - else - { - ulHashTable[ 1 ] |= ( 1 << ( ucEntry % 32 ) ); - } - - ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + return ~ulCRC32; } /*---------------------------------------------------------------------------*/ @@ -1141,7 +1330,7 @@ static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) .eEventType = eNetworkRxEvent, .pvData = ( void * ) pxDescriptor }; - if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_MAX_BLOCK_TIME_MS ) ) != pdPASS ) + if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_RX_MAX_BLOCK_TIME_MS ) ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvSendRxEvent: xSendEventStructToIPTask failed\n" ) ); @@ -1161,47 +1350,122 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI { HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); - const uint32_t uxL3FilterIds[ 2 ] = { ETH_L3_FILTER_0, ETH_L3_FILTER_1 }; - uint32_t uxL3FilterIdIndex = 0; - - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + if( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) { - ETH_L3FilterConfigTypeDef xL3FilterConfig; - /* #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) */ - if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + if( xMACConfig.ChecksumOffload != ENABLE ) { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex ], &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex++ ], &xL3FilterConfig ); + /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum + Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ + xMACConfig.ChecksumOffload = ENABLE; + ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); } - /* #if ( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) */ - else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + configASSERT( xMACConfig.ChecksumOffload == ENABLE ); + + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex ], &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, uxL3FilterIds[ uxL3FilterIdIndex++ ], &xL3FilterConfig ); - } + ETH_L3FilterConfigTypeDef xL3FilterConfig; + + /* Filter out all possibilities if frame type is disabled */ + if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) + { + /* Block IPv4 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; + xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + } + + if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) ) + { + /* Block IPv6 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } + + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + { + if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; + xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + } + } + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + { + if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } + } + } + } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ - if( uxL3FilterIdIndex >= ARRAY_SIZE( uxL3FilterIds ) ) + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) { - break; + /* TODO: Let user to block certain port numbers */ + /* TODO: Live updated in task based on active sockets? */ + ETH_L4FilterConfigTypeDef xL4FilterConfig; + + /* Always allow all UDP */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.SourcePort = 0U; + xL4FilterConfig.DestinationPort = 0U; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) + { + /* Block TCP if it is disabled */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.SourcePort = 0xFFFFU; + xL4FilterConfig.DestinationPort = 0xFFFFU; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + } } - } - /* TODO: This needs to be live updated based on sockets? */ - /* ETH_L4FilterConfigTypeDef xL4FilterConfigUDP; - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfigUDP ); - xL4FilterConfigUDP.Protocol = ETH_L4_UDP_MATCH; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfigUDP ); + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); - #if ( ipconfigIS_ENABLED( ipconfigUSE_TCP ) ) - ETH_L4FilterConfigTypeDef xL4FilterConfigTCP; - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfigTCP ); - xL4FilterConfigTCP.Protocol = ETH_L4_TCP_MATCH; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfigTCP ); - #endif */ - - HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); + } /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ } #endif /* ifdef niEMAC_STM32HX */ @@ -1233,20 +1497,20 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes break; } - /* TODO: Create a eConsiderPacketForProcessing */ - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - if( eConsiderPacketForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) + /* TODO: Should we do this even if it is handled in hardware too? */ + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet discarded\n" ) ); + FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); break; } #endif - /* TODO: Should we do this even if it is handled in hardware too? */ - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) - if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) + /* TODO: Create a eConsiderPacketForProcessing */ + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + if( eConsiderPacketForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { - FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); + FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet discarded\n" ) ); break; } #endif @@ -1278,55 +1542,67 @@ void ETH_IRQHandler( void ) void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA ) + eMAC_IF_EVENT eErrorEvents = eMacEventNone; + + if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) { - if( pxEthHandle->DMAErrorCode ) - { - if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) + /* Fatal bus error occurred */ + eErrorEvents |= eMacEventErrEth; + } + + if( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_DMA ) != 0 ) + { + eErrorEvents |= eMacEventErrDma; + /* if( pxEthHandle->DMAErrorCode & ETH_DMA_TX_PROCESS_STOPPED_FLAG ) */ + #ifdef niEMAC_STM32FX + if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMASR_TBUS ) != 0 ) { - /* Fatal bus error occurred */ - /* eMacEventErrDma */ - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrEth, eSetBits, &xHigherPriorityTaskWoken ); */ + eErrorEvents |= eMacEventErrTx; } - else - { - #ifdef niEMAC_STM32FX - if( pxEthHandle->DMAErrorCode & ETH_DMASR_TBUS ) - { - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ - } - if( pxEthHandle->DMAErrorCode & ETH_DMASR_RBUS ) - { - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); */ - } - #elif defined( niEMAC_STM32HX ) - if( pxEthHandle->DMAErrorCode & ETH_DMACSR_TBU ) - { - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrTx, eSetBits, &xHigherPriorityTaskWoken ); */ - } + if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMASR_RBUS ) != 0 ) + { + eErrorEvents |= eMacEventErrRx; + } + #elif defined( niEMAC_STM32HX ) + if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMACSR_TBU ) != 0 ) + { + eErrorEvents |= eMacEventErrTx; + } - if( pxEthHandle->DMAErrorCode & ETH_DMACSR_RBU ) - { - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrRx, eSetBits, &xHigherPriorityTaskWoken ); */ - } - #endif + if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) + { + eErrorEvents |= eMacEventErrRx; } - } + #endif } - if( pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC ) + if( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_MAC ) != 0 ) { - if( pxEthHandle->MACErrorCode ) - { - /* ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventErrMac, eSetBits, &xHigherPriorityTaskWoken ); */ - } + /*if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_RECEIVE_WATCHDOG_TIMEOUT ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_EXECESSIVE_COLLISIONS ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_LATE_COLLISIONS ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_EXECESSIVE_DEFERRAL ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_LOSS_OF_CARRIER ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_NO_CARRIER ) != 0 ) + if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_TRANSMIT_JABBR_TIMEOUT ) != 0 )*/ + eErrorEvents |= eMacEventErrMac; } - configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + /* if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_DRIBBLE_BIT_ERROR ) != 0 ) + if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_RECEIVE_ERROR ) != 0 ) + if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_RECEIVE_OVERFLOW ) != 0 ) + if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_WATCHDOG_TIMEOUT ) != 0 ) + if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_GIANT_PACKET ) != 0 ) + if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_CRC_ERROR ) != 0 ) + eErrorEvents |= eMacEventErrEth; */ - xSwitchRequired |= xHigherPriorityTaskWoken; + if( ( xEMACTaskHandle != NULL ) && ( eErrorEvents != eMacEventNone ) ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eErrorEvents, eSetBits, &xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; + } } /*---------------------------------------------------------------------------*/ @@ -1344,9 +1620,12 @@ void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) iptraceNETWORK_INTERFACE_RECEIVE(); - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventRx, eSetBits, &xHigherPriorityTaskWoken ); - xSwitchRequired |= xHigherPriorityTaskWoken; + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventRx, eSetBits, &xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; + } } /*---------------------------------------------------------------------------*/ @@ -1364,11 +1643,35 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) iptraceNETWORK_INTERFACE_TRANSMIT(); - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); - xSwitchRequired |= xHigherPriorityTaskWoken; + if( xEMACTaskHandle != NULL ) + { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + ( void ) xTaskNotifyFromISR( xEMACTaskHandle, eMacEventTx, eSetBits, &xHigherPriorityTaskWoken ); + xSwitchRequired |= xHigherPriorityTaskWoken; + } } +/*---------------------------------------------------------------------------*/ + +#ifdef niEMAC_STM32HX + +void HAL_ETH_EEECallback( ETH_HandleTypeDef * pxEthHandle ) +{ + switch( HAL_ETHEx_GetMACLPIEvent( pxEthHandle ) ) + { + case ETH_TX_LPI_ENTRY: + case ETH_TX_LPI_EXIT: + case ETH_RX_LPI_ENTRY: + case ETH_RX_LPI_EXIT: + break; + + default: + configASSERT( pdFALSE ); + } +} + +#endif + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* HAL Tx/Rx Callbacks */ @@ -1427,9 +1730,9 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) { - configASSERT( pulBuff ); NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) pulBuff; prvReleaseNetworkBufferDescriptor( pxNetworkBuffer ); + ( void ) xSemaphoreGive( xTxDescSem ); } /*---------------------------------------------------------------------------*/ @@ -1682,7 +1985,7 @@ void MPU_Config(void) MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; From c7cfcd6f17e404bb02e739c4896a3d369a4f95d9 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 22 Jan 2024 02:40:59 -0500 Subject: [PATCH 45/68] fix mac filtering --- .../NetworkInterface/STM32/NetworkInterface.c | 647 ++++++++++-------- 1 file changed, 372 insertions(+), 275 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 31da750d82..1fcaebea25 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -257,7 +257,6 @@ typedef enum BaseType_t xSwitchRequired; eMAC_INIT_STATUS_TYPE xMacInitStatus; BaseType_t xEMACIndex; - MACAddress_t xMatchedMacAddresses[ 3 ]; UBaseType_t uxMACEntry; } EMACData_t; */ @@ -288,19 +287,27 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); +#ifdef niEMAC_STM32HX + static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); +#endif static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); +/* MAC Filtering Helpers */ +static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ); +static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex, const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex ); +static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); +static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); +static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ); +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ); +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); + /* EMAC Helpers */ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ); static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); -static uint32_t prvCalcCrc32( const uint8_t * pucMAC ); static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ); static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ); - -/* Filter Helpers */ -#ifdef niEMAC_STM32HX - static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); -#endif static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ); /* Network Interface Definition */ @@ -330,9 +337,7 @@ static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; /* Src Mac Matching */ /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ -/* TODO: Stil need to check if new address matches ETH_MAC_ADDRESS0 */ -static const uint32_t xMacAddressEntries[ niEMAC_MAC_SRC_MATCH_COUNT ] = { ETH_MAC_ADDRESS1, ETH_MAC_ADDRESS2, ETH_MAC_ADDRESS3 }; -static MACAddress_t xMatchedMacAddresses[ niEMAC_MAC_SRC_MATCH_COUNT ]; +static const uint32_t xSrcMatchRegOffets[ niEMAC_MAC_SRC_MATCH_COUNT ] = { ETH_MAC_ADDRESS1, ETH_MAC_ADDRESS2, ETH_MAC_ADDRESS3 }; static uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ] = { 0U }; static uint8_t uxMACEntryIndex = 0; @@ -651,67 +656,20 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) { - BaseType_t xFoundMatch = pdFALSE; - for( UBaseType_t uxIndex = 0; uxIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++uxIndex ) - { - if( ucSrcMatchCounters[ uxIndex ] > 0U ) - { - /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ - if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) - { - /* Already assigned this mac address */ - ++( ucSrcMatchCounters[ uxIndex ] ); - xFoundMatch = pdTRUE; - break; - } - } - else - { - if( uxMACEntryIndex > niEMAC_MAC_SRC_MATCH_COUNT ) - { - uxMACEntryIndex = niEMAC_MAC_SRC_MATCH_COUNT; - } - } - } + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + + /* TODO: group address filtering with Mask Byte Control */ + BaseType_t xResult = prvAddDestMACAddrMatch( pxEthHandle, pucMacAddress ); - if( xFoundMatch == pdFALSE ) + if( xResult == pdFALSE ) { - ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + const uint8_t ucHashIndex = prvGetMacHashIndex( pucMacAddress ); - const uint32_t ulHash = prvCalcCrc32( pucMacAddress ); - const uint8_t ucHashIndex = ( ulHash >> 26 ) & 0x3FU; + xResult = prvSetNewDestMACAddrMatch( pxEthHandle, ucHashIndex, pucMacAddress ); - if( uxMACEntryIndex < niEMAC_MAC_SRC_MATCH_COUNT ) + if( xResult == pdFALSE ) { - if( ucAddrHashCounters[ ucHashIndex ] == 0U ) - { - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, xMacAddressEntries[ uxMACEntryIndex ], ( uint8_t * ) pucMacAddress ); - ( void ) memcpy( xMatchedMacAddresses[ uxMACEntryIndex ].ucBytes, pucMacAddress, ipMAC_ADDRESS_LENGTH_BYTES ); - ucSrcMatchCounters[ uxMACEntryIndex ] = 1U; - xFoundMatch = pdTRUE; - } - } - - if( xFoundMatch == pdFALSE ) - { - if( ucAddrHashCounters[ ucHashIndex ] == 0 ) - { - if( ucHashIndex & 0x20U ) - { - ulHashTable[ 1 ] |= ( 1U << ( ucHashIndex & 0x1FU ) ); - } - else - { - ulHashTable[ 0 ] |= ( 1U << ucHashIndex ); - } - - ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); - } - - if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) - { - ++( ucAddrHashCounters[ ucHashIndex ] ); - } + prvAddDestMACAddrHash( pxEthHandle, ucHashIndex ); } } } @@ -721,57 +679,12 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; - BaseType_t xFoundMatch = pdFALSE; - for( UBaseType_t uxIndex = 0; uxIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++uxIndex ) - { - if( ucSrcMatchCounters[ uxIndex ] > 0U ) - { - /* Temporary inefficient method to avoid writing a HAL_ETH_GetSourceMACAddrMatch for Hx & Fx */ - if( memcmp( pucMacAddress, xMatchedMacAddresses[ uxIndex ].ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ) == 0 ) - { - if( ucSrcMatchCounters[ uxIndex ] < UINT8_MAX ) - { - --( ucSrcMatchCounters[ uxIndex ] ); - if( ucSrcMatchCounters[ uxIndex ] == 0 ) - { - /* TODO: Just disable it, don't need to clear? */ - ( void ) memset( &( xMatchedMacAddresses[ uxIndex ].ucBytes ), 0, ipMAC_ADDRESS_LENGTH_BYTES ); - ( void ) HAL_ETH_SetSourceMACAddrMatch( pxEthHandle, xMacAddressEntries[ uxIndex ], xMatchedMacAddresses[ uxIndex ].ucBytes ); - } - } - xFoundMatch = pdTRUE; - break; - } - } - } + const BaseType_t xResult = prvRemoveDestMACAddrMatch( pxEthHandle, pucMacAddress ); - if( xFoundMatch == pdFALSE ) + if( xResult == pdFALSE ) { - const uint32_t ulHash = prvCalcCrc32( pucMacAddress ); - const uint8_t ucHashIndex = ( ulHash >> 26 ) & 0x3FU; - - if( ucAddrHashCounters[ ucHashIndex ] > 0U ) - { - if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) - { - --( ucAddrHashCounters[ ucHashIndex ] ); - - if( ucAddrHashCounters[ ucHashIndex ] == 0 ) - { - if( ucHashIndex & 0x20U ) - { - ulHashTable[ 1 ] &= ~( 1U << ( ucHashIndex & 0x1FU ) ); - } - else - { - ulHashTable[ 0 ] &= ~( 1U << ucHashIndex ); - } - - ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); - } - } - } + prvRemoveDestMACAddrHash( pxEthHandle, pucMacAddress ); } } @@ -1172,6 +1085,134 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkI /*---------------------------------------------------------------------------*/ +#ifdef niEMAC_STM32HX + +static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ) +{ + HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); + + if( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) + { + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + if( xMACConfig.ChecksumOffload != ENABLE ) + { + /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum + Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ + xMACConfig.ChecksumOffload = ENABLE; + ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); + } + configASSERT( xMACConfig.ChecksumOffload == ENABLE ); + + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + { + ETH_L3FilterConfigTypeDef xL3FilterConfig; + + /* Filter out all possibilities if frame type is disabled */ + if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) + { + /* Block IPv4 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; + xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + } + + if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) ) + { + /* Block IPv6 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } + + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + { + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + { + if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; + xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + } + } + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + { + if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } + } + } + } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ + + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + { + /* TODO: Let user to block certain port numbers */ + /* TODO: Live updated in task based on active sockets? */ + ETH_L4FilterConfigTypeDef xL4FilterConfig; + + /* Always allow all UDP */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.SourcePort = 0U; + xL4FilterConfig.DestinationPort = 0U; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) + { + /* Block TCP if it is disabled */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.SourcePort = 0xFFFFU; + xL4FilterConfig.DestinationPort = 0xFFFFU; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + } + } + + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); + + } /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ +} + +#endif /* ifdef niEMAC_STM32HX */ + +/*---------------------------------------------------------------------------*/ + static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -1219,7 +1260,221 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface /*---------------------------------------------------------------------------*/ /*===========================================================================*/ -/* EMAC Helpers */ +/* MAC Filtering Helpers */ +/*===========================================================================*/ +/*---------------------------------------------------------------------------*/ + +/* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ +static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ) +{ + uint32_t ulCRC32 = 0xFFFFFFFFU; + + for( uint32_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) + { + ulCRC32 ^= __RBIT( pucMACAddr[ ipMAC_ADDRESS_LENGTH_BYTES - ucIndex ] ); + + for( uint8_t ucJndex = 8; ucJndex > 0; --ucJndex ) + { + if( ulCRC32 & 0x80000000U ) + { + ulCRC32 <<= 1; + ulCRC32 ^= niEMAC_CRC_POLY; + } + else + { + ulCRC32 <<= 1; + } + } + } + + return ~ulCRC32; +} + +/*---------------------------------------------------------------------------*/ + +static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ) +{ + const uint32_t ulHash = prvCalcCrc32( pucMACAddr ); + const uint8_t ucHashIndex = ( ulHash >> 26 ) & 0x3FU; + + return ucHashIndex; +} + +/*---------------------------------------------------------------------------*/ + +/* Needed since HAL Driver only provides source matching */ +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex, const uint8_t * const pucMACAddr ) +{ + /* Get mac addr high reg offset */ + const uint32_t macaddrhr = ((uint32_t) &(pxEthHandle->Instance->MACA0HR) + xSrcMatchRegOffets[ ucIndex ]); + /* Get mac addr low reg offset */ + const uint32_t macaddrlr = ((uint32_t) &(pxEthHandle->Instance->MACA0LR) + xSrcMatchRegOffets[ ucIndex ]); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pucMACAddr[5]) << 8) | (uint32_t)pucMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pucMACAddr[3]) << 24) | ((uint32_t)(pucMACAddr[2]) << 16) | + ((uint32_t)(pucMACAddr[1]) << 8) | (uint32_t)pucMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= ETH_MACA1HR_AE; +} + +/*---------------------------------------------------------------------------*/ + +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex ) +{ + /* Get mac addr high reg offset */ + const uint32_t macaddrhr = ((uint32_t) &(pxEthHandle->Instance->MACA0HR) + xSrcMatchRegOffets[ ucIndex ]); + /* Get mac addr low reg offset */ + const uint32_t macaddrlr = ((uint32_t) &(pxEthHandle->Instance->MACA0LR) + xSrcMatchRegOffets[ ucIndex ]); + + /* Clears MAC addr bits 32 to 47 and ETH_MACAHR_AE */ + (*(__IO uint32_t *)macaddrhr) = 0; + /* Clears MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = 0; +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +{ + BaseType_t xResult = pdFALSE; + + for( uint8_t ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) + { + if( ucSrcMatchCounters[ ucIndex ] > 0U ) + { + const uint32_t ulNewMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); + const uint32_t ulNewMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); + + const uint32_t ulMacAddrHigh = ( ( ( uint32_t ) &( pxEthHandle->Instance->MACA0HR ) + xSrcMatchRegOffets[ ucIndex ] ) & 0x0000FFFFU ); + const uint32_t ulMacAddrLow = ( ( uint32_t ) &( pxEthHandle->Instance->MACA0LR ) + xSrcMatchRegOffets[ ucIndex ]); + + if( ( ulNewMacAddrHigh == ulMacAddrHigh ) && ( ulNewMacAddrLow == ulMacAddrLow ) ) + { + ++( ucSrcMatchCounters[ ucIndex ] ); + xResult = pdTRUE; + break; + } + } + else if( uxMACEntryIndex > niEMAC_MAC_SRC_MATCH_COUNT ) + { + uxMACEntryIndex = niEMAC_MAC_SRC_MATCH_COUNT; + } + } + + return xResult; +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +{ + BaseType_t xResult = pdFALSE; + + for( uint8_t ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) + { + if( ucSrcMatchCounters[ ucIndex ] > 0U ) + { + const uint32_t ulNewMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); + const uint32_t ulNewMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); + + const uint32_t ulMacAddrHigh = ( ( ( uint32_t ) &( pxEthHandle->Instance->MACA0HR ) + xSrcMatchRegOffets[ ucIndex ] ) & 0x0000FFFFU ); + const uint32_t ulMacAddrLow = ( ( uint32_t ) &( pxEthHandle->Instance->MACA0LR ) + xSrcMatchRegOffets[ ucIndex ]); + + if( ( ulNewMacAddrHigh == ulMacAddrHigh ) && ( ulNewMacAddrLow == ulMacAddrLow ) ) + { + if( ucSrcMatchCounters[ ucIndex ] < UINT8_MAX ) + { + if( --( ucSrcMatchCounters[ ucIndex ] ) == 0 ) + { + prvHAL_ETH_ClearDestMACAddrMatch( pxEthHandle, ucIndex ); + } + } + + xResult = pdTRUE; + break; + } + } + } + + return xResult; +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ) +{ + BaseType_t xResult = pdFALSE; + + if( uxMACEntryIndex < niEMAC_MAC_SRC_MATCH_COUNT ) + { + if( ucAddrHashCounters[ ucHashIndex ] == 0U ) + { + prvHAL_ETH_SetDestMACAddrMatch( pxEthHandle, uxMACEntryIndex, pucMACAddr ); + ucSrcMatchCounters[ uxMACEntryIndex ] = 1U; + xResult = pdTRUE; + } + } + + return xResult; +} + +/*---------------------------------------------------------------------------*/ + +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ) +{ + if( ucAddrHashCounters[ ucHashIndex ] == 0 ) + { + if( ucHashIndex & 0x20U ) + { + ulHashTable[ 1 ] |= ( 1U << ( ucHashIndex & 0x1FU ) ); + } + else + { + ulHashTable[ 0 ] |= ( 1U << ucHashIndex ); + } + + ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + } + + if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) + { + ++( ucAddrHashCounters[ ucHashIndex ] ); + } +} + +/*---------------------------------------------------------------------------*/ + +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +{ + const uint8_t ucHashIndex = prvGetMacHashIndex( pucMACAddr ); + + if( ucAddrHashCounters[ ucHashIndex ] > 0U ) + { + if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) + { + if( --ucAddrHashCounters[ ucHashIndex ] == 0 ) + { + if( ucHashIndex & 0x20U ) + { + ulHashTable[ 1 ] &= ~( 1U << ( ucHashIndex & 0x1FU ) ); + } + else + { + ulHashTable[ 0 ] &= ~( 1U << ucHashIndex ); + } + + ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + } + } + } +} + +/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* EMAC Helpers */ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ @@ -1242,6 +1497,8 @@ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ) } */ } +/*---------------------------------------------------------------------------*/ + static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -1279,34 +1536,6 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP /*---------------------------------------------------------------------------*/ -/* Compute the CRC32 of the given MAC address as per IEEE 802.3 CRC32 */ -static uint32_t prvCalcCrc32( const uint8_t * pucMAC ) -{ - uint32_t ulCRC32 = 0xFFFFFFFFU; - - for( uint32_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) - { - ulCRC32 ^= __RBIT( pucMAC[ ipMAC_ADDRESS_LENGTH_BYTES - ucIndex ] ); - - for( uint8_t ucJndex = 8; ucJndex > 0; --ucJndex ) - { - if( ulCRC32 & 0x80000000U ) - { - ulCRC32 <<= 1; - ulCRC32 ^= niEMAC_CRC_POLY; - } - else - { - ulCRC32 <<= 1; - } - } - } - - return ~ulCRC32; -} - -/*---------------------------------------------------------------------------*/ - static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ) { NetworkBufferDescriptor_t * pxDescriptorToClear = pxDescriptor; @@ -1338,138 +1567,6 @@ static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) } } -/*---------------------------------------------------------------------------*/ -/*===========================================================================*/ -/* Filter Helpers */ -/*===========================================================================*/ -/*---------------------------------------------------------------------------*/ - -#ifdef niEMAC_STM32HX - -static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ) -{ - HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); - - if( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) - { - ETH_MACConfigTypeDef xMACConfig; - ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - if( xMACConfig.ChecksumOffload != ENABLE ) - { - /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum - Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ - xMACConfig.ChecksumOffload = ENABLE; - ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); - } - configASSERT( xMACConfig.ChecksumOffload == ENABLE ); - - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) - { - ETH_L3FilterConfigTypeDef xL3FilterConfig; - - /* Filter out all possibilities if frame type is disabled */ - if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) - { - /* Block IPv4 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; - xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - } - - if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) ) - { - /* Block IPv6 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - } - - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - if( ENDPOINT_IS_IPv4( pxEndPoint ) ) - { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) - { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; - xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - } - } - else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) - { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) - { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - } - } - } - } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ - - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) - { - /* TODO: Let user to block certain port numbers */ - /* TODO: Live updated in task based on active sockets? */ - ETH_L4FilterConfigTypeDef xL4FilterConfig; - - /* Always allow all UDP */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.SourcePort = 0U; - xL4FilterConfig.DestinationPort = 0U; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - - if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) - { - /* Block TCP if it is disabled */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.SourcePort = 0xFFFFU; - xL4FilterConfig.DestinationPort = 0xFFFFU; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - } - } - - HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); - - } /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ -} - -#endif /* ifdef niEMAC_STM32HX */ - /*---------------------------------------------------------------------------*/ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ) From 3b85eaef6d5c3a164842eaa83b4e927a94edd252 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 22 Jan 2024 04:28:02 -0500 Subject: [PATCH 46/68] outgoing packet adjustments --- .../NetworkInterface/STM32/NetworkInterface.c | 155 +++++++++++------- 1 file changed, 95 insertions(+), 60 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 1fcaebea25..e292d5768d 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -120,6 +120,9 @@ #define niEMAC_AUTO_LOW_POWER ( ipconfigDISABLE && ipconfigIS_DISABLED( niEMAC_USE_RMII ) ) #endif +#define niEMAC_TCP_SEGMENTATION ipconfigDISABLE +#define niEMAC_ARP_OFFLOAD ipconfigDISABLE + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Config Checks */ @@ -522,20 +525,6 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); - break; - } - - if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_TX_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) - { - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); - ( void ) xSemaphoreGive( xTxDescSem ); - /* TODO: Can we queue it? */ - break; - } - /* static ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ] = { 0 }; */ static ETH_TxPacketConfig xTxConfig = { @@ -559,63 +548,93 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; #endif - #if 0 - - const EthernetHeader_t * const pxEthHeader = ( const EthernetHeader_t * const ) pxDescriptor->pucEthernetBuffer; - - if( pxEthHeader->usFrameType == ipIPv4_FRAME_TYPE ) - { - #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) - const IPPacket_t * const pxIPPacket = ( const IPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + const EthernetHeader_t * const pxEthHeader = ( const EthernetHeader_t * const ) pxDescriptor->pucEthernetBuffer; + if( pxEthHeader->usFrameType == ipIPv4_FRAME_TYPE ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + const IPPacket_t * const pxIPPacket = ( const IPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + /* ProtocolPacket_t * const pxIPPacket = ( ProtocolPacket_t * const ) pxDescriptor->pucEthernetBuffer; */ + /* ProtocolHeaders_t * const pxIPPacket = ( ProtocolHeaders_t * const ) pxDescriptor->pucEthernetBuffer; */ - if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) - { + if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) + { + #if ipconfigIS_ENABLED( ipconfigREPLY_TO_INCOMING_PINGS ) || ipconfigIS_ENABLED( ipconfigSUPPORT_OUTGOING_PINGS ) ICMPPacket_t * const pxICMPPacket = ( ICMPPacket_t * const ) pxDescriptor->pucEthernetBuffer; #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) pxICMPPacket->xICMPHeader.usChecksum = 0U; #endif - } - else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_TCP ) - { + ( void ) pxICMPPacket; + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported ICMP\n" ) ); + #endif + } + else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_TCP ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) TCPPacket_t * const pxTCPPacket = ( TCPPacket_t * const ) pxDescriptor->pucEthernetBuffer; - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) /* && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) */ - /* pxTCPSocketLookup */ - xTxConfig.PayloadLen = pxTCPPacket->xIPHeader.usLength; - xTxConfig.TCPHeaderLen = ( ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ) * 4U ); + /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) + xTxConfig.PayloadLen = pxDescriptor->xDataLength; + xTxConfig.TCPHeaderLen = ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ); xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif - } - #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ - } - else if( pxEthHeader->usFrameType == ipIPv6_FRAME_TYPE ) - { - /* #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ - const IPPacket_IPv6_t * pxIPPacket_IPv6 = ( IPPacket_IPv6_t * ) pxDescriptor->pucEthernetBuffer; + #endif */ + ( void ) pxTCPPacket; + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); + #endif + } + else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_UDP ) + { + UDPPacket_t * const pxUDPPacket = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + ( void ) pxUDPPacket; + } + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv4\n" ) ); + #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + } + else if( pxEthHeader->usFrameType == ipIPv6_FRAME_TYPE ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + const IPPacket_IPv6_t * pxIPPacket_IPv6 = ( IPPacket_IPv6_t * ) pxDescriptor->pucEthernetBuffer; - if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_ICMP_IPv6 ) - { + if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_ICMP_IPv6 ) + { + #if ipconfigIS_ENABLED( ipconfigREPLY_TO_INCOMING_PINGS ) || ipconfigIS_ENABLED( ipconfigSUPPORT_OUTGOING_PINGS ) ICMPPacket_IPv6_t * const pxICMPPacket_IPv6 = ( ICMPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) pxICMPPacket_IPv6->xICMPHeaderIPv6.usChecksum = 0U; #endif - } - else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_TCP ) - { + ( void ) pxICMPPacket_IPv6; + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported ICMP\n" ) ); + #endif + } + else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_TCP ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) TCPPacket_IPv6_t * const pxTCPPacket_IPv6 = ( TCPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) /* && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) */ - xTxConfig.PayloadLen = pxTCPPacket_IPv6->xIPHeader.usPayloadLength; + /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) + xTxConfig.PayloadLen = pxDescriptor->xDataLength; xTxConfig.TCPHeaderLen = sizeof( pxTCPPacket_IPv6->xTCPHeader ); xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif - } - /* #endif */ /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ - } - else if( pxEthHeader->usFrameType == ipARP_FRAME_TYPE ) - { - - } + #endif */ + ( void ) pxTCPPacket_IPv6; + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); + #endif + } + else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_UDP ) + { + UDPPacket_t * const pxUDPPacket_IPv6 = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + ( void ) pxUDPPacket_IPv6; + } + #else + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv6\n" ) ); + #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ + } + else if( pxEthHeader->usFrameType == ipARP_FRAME_TYPE ) + { - #endif + } ETH_BufferTypeDef xTxBuffer = { .buffer = pxDescriptor->pucEthernetBuffer, @@ -627,6 +646,20 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.Length = xTxBuffer.len; + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); + break; + } + + if( xSemaphoreTake( xTxMutex, pdMS_TO_TICKS( niEMAC_TX_MAX_BLOCK_TIME_MS ) ) == pdFALSE ) + { + FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); + ( void ) xSemaphoreGive( xTxDescSem ); + /* TODO: Can we queue it? */ + break; + } + if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) { /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ @@ -969,19 +1002,21 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo xDMAConfig.EnhancedDescriptorFormat = ( FunctionalState ) ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) || ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ); #elif defined( niEMAC_STM32HX ) xDMAConfig.SecondPacketOperate = ENABLE; - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) && ipconfigIS_DISABLED( ipconfigUSE_TCP_WIN ) + /* #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) xDMAConfig.TCPSegmentation = ENABLE; xDMAConfig.MaximumSegmentSize = ipconfigTCP_MSS; - #endif + #endif */ #endif ( void ) HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ); #if defined( niEMAC_STM32HX ) prvInitPacketFilter( pxEthHandle, pxInterface ); - /* HAL_ETHEx_DisableARPOffload( pxEthHandle ); - HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); - HAL_ETHEx_EnableARPOffload( pxEthHandle ); */ + /* #if ipconfigIS_ENABLED( niEMAC_ARP_OFFLOAD ) + HAL_ETHEx_DisableARPOffload( pxEthHandle ); + HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); + HAL_ETHEx_EnableARPOffload( pxEthHandle ); + #endif */ #endif prvInitMacAddresses( pxEthHandle, pxInterface ); From 86fcd67e1a4895ab322f0433c3d40ca8bea181d6 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Mon, 22 Jan 2024 17:54:36 +0300 Subject: [PATCH 47/68] fix interrupt priority set --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index e292d5768d..a820f8bff1 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1038,12 +1038,11 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo } #endif - uint32_t ulPreemptPriority, ulSubPriority; - HAL_NVIC_GetPriority( ETH_IRQn, HAL_NVIC_GetPriorityGrouping(), &ulPreemptPriority, &ulSubPriority ); - if( ulPreemptPriority < configMAX_FREERTOS_INTERRUPT_PRIORITY ) + uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8 - configPRIO_BITS ); + if( ulPriority < configMAX_SYSCALL_INTERRUPT_PRIORITY ) { FreeRTOS_debug_printf( ( "prvEthConfigInit: Incorrectly set ETH_IRQn priority\n" ) ); - HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_FREERTOS_INTERRUPT_PRIORITY, 0 ); + NVIC_SetPriority( ETH_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY >> ( 8 - configPRIO_BITS ) ); } if( NVIC_GetEnableIRQ( ETH_IRQn ) == 0 ) { From 270b1f8b9a1b97b00875f9931af51106ce555f38 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 24 Jan 2024 19:02:07 -0500 Subject: [PATCH 48/68] remove C99 requirement --- .../NetworkInterface/STM32/NetworkInterface.c | 63 ++++++++++--------- 1 file changed, 35 insertions(+), 28 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index a820f8bff1..0f52671b05 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -279,8 +279,8 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); -static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ); -static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ); +static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ); /* EMAC Task */ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); @@ -288,8 +288,8 @@ static __NO_RETURN portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ); static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ -static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ); +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); #ifdef niEMAC_STM32HX static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); #endif @@ -531,16 +531,16 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, .Length = 0U, .TxBuffer = NULL, - .SrcAddrCtrl = ETH_SRC_ADDR_CONTROL_DISABLE, + /* .SrcAddrCtrl = ETH_SRC_ADDR_CONTROL_DISABLE, */ .CRCPadCtrl = ETH_CRC_PAD_INSERT, .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, .MaxSegmentSize = ipconfigTCP_MSS, .PayloadLen = 0U, .TCPHeaderLen = 0U, .VlanTag = 0U, - .VlanCtrl = ETH_VLAN_DISABLE, + /* .VlanCtrl = ETH_VLAN_DISABLE, */ .InnerVlanTag = 0U, - .InnerVlanCtrl = ETH_INNER_VLAN_DISABLE, + /* .InnerVlanCtrl = ETH_INNER_VLAN_DISABLE, */ .pData = NULL, }; @@ -687,7 +687,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /*---------------------------------------------------------------------------*/ -static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) +static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; @@ -709,7 +709,7 @@ static void prvAddAllowedMACAddress( const uint8_t * pucMacAddress ) /*---------------------------------------------------------------------------*/ -static void prvRemoveAllowedMACAddress( const uint8_t * pucMacAddress ) +static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; @@ -937,7 +937,7 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ) +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { BaseType_t xResult = pdFALSE; @@ -1038,7 +1038,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo } #endif - uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8 - configPRIO_BITS ); + const uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8 - configPRIO_BITS ); if( ulPriority < configMAX_SYSCALL_INTERRUPT_PRIORITY ) { FreeRTOS_debug_printf( ( "prvEthConfigInit: Incorrectly set ETH_IRQn priority\n" ) ); @@ -1070,7 +1070,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, const Netwo /*---------------------------------------------------------------------------*/ -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * pxInterface ) +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) { ETH_MACFilterConfigTypeDef xFilterConfig; ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); @@ -1092,9 +1092,10 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, const NetworkI xFilterConfig.PromiscuousMode = DISABLE; ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) + NetworkEndPoint_t * pxEndPoint; + for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - prvAddAllowedMACAddress( pxEndPoint->xMACAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, pxEndPoint->xMACAddress.ucBytes ); } #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) @@ -1303,11 +1304,13 @@ static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ) { uint32_t ulCRC32 = 0xFFFFFFFFU; - for( uint32_t ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) + uint32_t ucIndex; + for( ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) { ulCRC32 ^= __RBIT( pucMACAddr[ ipMAC_ADDRESS_LENGTH_BYTES - ucIndex ] ); - for( uint8_t ucJndex = 8; ucJndex > 0; --ucJndex ) + uint8_t ucJndex; + for( ucJndex = 8; ucJndex > 0; --ucJndex ) { if( ulCRC32 & 0x80000000U ) { @@ -1375,7 +1378,8 @@ static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const { BaseType_t xResult = pdFALSE; - for( uint8_t ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) + uint8_t ucIndex; + for( ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) { if( ucSrcMatchCounters[ ucIndex ] > 0U ) { @@ -1407,7 +1411,8 @@ static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, co { BaseType_t xResult = pdFALSE; - for( uint8_t ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) + uint8_t ucIndex; + for( ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) { if( ucSrcMatchCounters[ ucIndex ] > 0U ) { @@ -1610,6 +1615,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes { if( pxDescriptor == NULL ) { + iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Null Descriptor\n" ) ); break; } @@ -1618,12 +1624,20 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); if( ulErrorCode != 0 ) { + iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); break; } + /* if( ( ulErrorCode & ETH_DRIBBLE_BIT_ERROR ) != 0 ) + if( ( ulErrorCode & ETH_RECEIVE_ERROR ) != 0 ) + if( ( ulErrorCode & ETH_RECEIVE_OVERFLOW ) != 0 ) + if( ( ulErrorCode & ETH_WATCHDOG_TIMEOUT ) != 0 ) + if( ( ulErrorCode & ETH_GIANT_PACKET ) != 0 ) + if( ( ulErrorCode & ETH_CRC_ERROR ) != 0 ) */ if( usLength > niEMAC_DATA_BUFFER_SIZE ) { + iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); break; } @@ -1720,14 +1734,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) eErrorEvents |= eMacEventErrMac; } - /* if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_DRIBBLE_BIT_ERROR ) != 0 ) - if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_RECEIVE_ERROR ) != 0 ) - if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_RECEIVE_OVERFLOW ) != 0 ) - if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_WATCHDOG_TIMEOUT ) != 0 ) - if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_GIANT_PACKET ) != 0 ) - if( ( HAL_ETH_GetError( pxEthHandle ) & ETH_CRC_ERROR ) != 0 ) - eErrorEvents |= eMacEventErrEth; */ - if( ( xEMACTaskHandle != NULL ) && ( eErrorEvents != eMacEventNone ) ) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; @@ -1878,7 +1884,8 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB configASSERT( xBufferAllocFixedSize == pdTRUE ); - for( size_t uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++uxIndex ) + size_t uxIndex; + for( uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++uxIndex ) { pxNetworkBuffers[ uxIndex ].pucEthernetBuffer = &( ucNetworkPackets[ uxIndex ][ ipBUFFER_PADDING ] ); *( ( uint32_t * ) &( ucNetworkPackets[ uxIndex ][ 0 ] ) ) = ( uint32_t ) ( &( pxNetworkBuffers[ uxIndex ] ) ); @@ -2066,7 +2073,7 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) } /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_FREERTOS_INTERRUPT_PRIORITY, 0 ); + HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY, 0 ); HAL_NVIC_EnableIRQ( ETH_IRQn ); } } From 8549ed52e8cc5adad7d36affd3ac5909f1418666 Mon Sep 17 00:00:00 2001 From: Holden Date: Sun, 28 Jan 2024 21:48:13 -0500 Subject: [PATCH 49/68] readd caching and reduce reliance on HAL --- .../NetworkInterface/STM32/NetworkInterface.c | 1343 ++++++++++++----- 1 file changed, 985 insertions(+), 358 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 0f52671b05..b69c5dbb09 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -71,6 +71,16 @@ #error "Unknown STM32 Family for NetworkInterface" #endif +#if defined( STM32H5 ) || defined( STM32H7 ) + /* #ifdef LAN8742A_PHY_ADDRESS */ + #include "lan8742/lan8742.h" + /* #endif */ + + /* #ifdef DP83848_PHY_ADDRESS */ + #include "dp83848/dp83848.h" + /* #endif */ +#endif + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Config */ @@ -83,45 +93,40 @@ #define niEMAC_STM32HX #endif +#define niEMAC_TASK_NAME "EMAC_STM32" +#define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) + #define niEMAC_TX_DESC_SECTION ".TxDescripSection" #define niEMAC_RX_DESC_SECTION ".RxDescripSection" #define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -#define niEMAC_DATA_ALIGNMENT 4U -#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) -#define niEMAC_BUF_ALIGNMENT 32U -#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1U ) - -#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) - #define niEMAC_TASK_MAX_BLOCK_TIME_MS 100U #define niEMAC_TX_MAX_BLOCK_TIME_MS 20U #define niEMAC_RX_MAX_BLOCK_TIME_MS 20U #define niEMAC_DESCRIPTOR_WAIT_TIME_MS 20U -#define niEMAC_TASK_NAME "EMAC_STM32" -#define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) -#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) - #define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" #define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" #define niEMAC_AUTO_NEGOTIATION ipconfigENABLE #define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) - #define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) #define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) #define niEMAC_USE_RMII ipconfigENABLE +#define niEMAC_USE_MPU ipconfigENABLE + #ifdef niEMAC_STM32HX #define niEMAC_AUTO_LOW_POWER ( ipconfigDISABLE && ipconfigIS_DISABLED( niEMAC_USE_RMII ) ) + #define niEMAC_TCP_SEGMENTATION ipconfigDISABLE + #define niEMAC_ARP_OFFLOAD ipconfigDISABLE + #define niEMAC_USE_PHY_INT ipconfigDISABLE #endif -#define niEMAC_TCP_SEGMENTATION ipconfigDISABLE -#define niEMAC_ARP_OFFLOAD ipconfigDISABLE +#define niEMAC_DEBUG_ERROR ipconfigDISABLE /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -159,19 +164,14 @@ #error "Invalid ETH_RX_DESC_CNT value for NetworkInterface, must be a multiple of 4" #endif -#elif defined( niEMAC_STM32FX ) - - #if defined( ETH_RX_BUF_SIZE ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - /* __STM32F7xx_HAL_VERSION, __STM32F4xx_HAL_VERSION */ - #warning "As of F7 V1.17.1 && F4 V1.28.0, a bug exists in the ETH HAL Driver where ETH_RX_BUF_SIZE is used instead of RxBuffLen, so ETH_RX_BUF_SIZE must == niEMAC_DATA_BUFFER_SIZE" - #endif - #endif - #endif #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) + #if defined( niEMAC_STM32FX ) && defined( ETH_RX_BUF_SIZE ) + #warning "As of F7 V1.17.1 && F4 V1.28.0, a bug exists in the ETH HAL Driver where ETH_RX_BUF_SIZE is used instead of RxBuffLen, so ETH_RX_BUF_SIZE must == niEMAC_DATA_BUFFER_SIZE" + #endif + #if ipconfigIS_DISABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) #warning "Consider enabling ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM for NetworkInterface" #endif @@ -184,34 +184,85 @@ #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" #endif + /* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. + * So, don't use this macro, and filter anyways in the mean time. */ + /* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" + #endif */ + #if ipconfigIS_DISABLED( ipconfigUSE_LINKED_RX_MESSAGES ) - #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" + #warning "Consider enabling ipconfigUSE_LINKED_RX_MESSAGES for NetworkInterface" #endif #endif -/* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. - * So, don't use this macro, and filter anyways in the mean time. */ -/* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) - #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" - #endif -#endif */ - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Macros & Definitions */ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -#define niEMAC_BUFS_PER_DESC 2U +#define niEMAC_MPU ( defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) ) +#if ( niEMAC_MPU != 0 ) + #define niEMAC_MPU_ENABLED ( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ) +#endif + +#define niEMAC_CACHEABLE ( defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) ) +#if ( niEMAC_CACHEABLE != 0 ) + #define niEMAC_CACHE_ENABLED ( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) + #define niEMAC_CACHE_MAINTENANCE ( niEMAC_CACHE_ENABLED && ipconfigIS_DISABLED( niEMAC_USE_MPU ) ) + #ifdef __SCB_DCACHE_LINE_SIZE + #define niEMAC_DATA_ALIGNMENT __SCB_DCACHE_LINE_SIZE + #else + #define niEMAC_DATA_ALIGNMENT 32U + #endif +#else + #define niEMAC_DATA_ALIGNMENT 4U +#endif -/* TODO: Enabled and use interrupts for phy instead of polling? */ -/*#define niPHY_ISR_AN_COMPLETE 0x0040 -#define niPHY_ISR_LINK_DOWN 0x0010 +#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) +#define niEMAC_BUF_ALIGNMENT 32U +#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1U ) + +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) + +#if defined( niEMAC_STM32FX ) + + #ifdef ETH_GIANT_PACKET + #undef ETH_GIANT_PACKET + #endif + #define ETH_GIANT_PACKET ETH_DMARXDESC_IPV4HCE + + #ifdef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG + #undef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG + #endif + #define ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_RBUS + + #ifdef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG + #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG + #endif + #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_TBUS + + /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ + #ifdef ETH_CTRLPACKETS_BLOCK_ALL + #undef ETH_CTRLPACKETS_BLOCK_ALL + #endif + #define ETH_CTRLPACKETS_BLOCK_ALL ETH_MACFFR_PCF_BlockAll + +#elif defined( niEMAC_STM32HX ) + + #ifdef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG + #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG + #endif + #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMACSR_TBU -#define niPHY_IMR_AN_COMPLETE 0x0040 -#define niPHY_IMR_LINK_DOWN 0x0010*/ + #define ETH_DMA_TX_ERRORS_MASK ETH_DMACSR_TEB + #define ETH_DMA_RX_ERRORS_MASK ETH_DMACSR_REB + +#endif + +#define niEMAC_BUFS_PER_DESC 2U /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ #define niEMAC_CRC_POLY 0x04C11DB7 @@ -220,8 +271,6 @@ #define niEMAC_ADDRESS_HASH_BITS 64U #define niEMAC_MAC_SRC_MATCH_COUNT 3U -#define niEMAC_DEBUG( X, MSG ) if( ( X ) != 0 ) { FreeRTOS_debug_printf( ( MSG ) ); } - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* typedefs */ @@ -251,16 +300,46 @@ typedef enum eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; -/* typedef struct xEMACData +/* typedef struct xPhyData +{ + EthernetPhy_t xPhyObject; + #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) + union { + lan8742_Object_t xLan8742a; + dp83848_Object_t xDp83848; + } xPhyInstance; + #endif +} PhyData_t; + +typedef struct xMacSrcMatchData +{ + uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ]; + uint8_t uxMACEntryIndex = 0; +} MacSrcMatchData_t; + +typedef struct xMacHashData +{ + uint32_t ulHashTable[ niEMAC_ADDRESS_HASH_BITS / 32 ]; + uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ]; +} MacHashData_t; + +typedef struct xMacFilteringData +{ + MacSrcMatchData_t xSrcMatch; + MacHashData_t xHash; +} MacFilteringData_t; + +typedef struct xEMACData { ETH_HandleTypeDef xEthHandle; EthernetPhy_t xPhyObject; TaskHandle_t xEMACTaskHandle; - SemaphoreHandle_t xTxMutex; + SemaphoreHandle_t xTxMutex, xTxDescSem; + ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ]; BaseType_t xSwitchRequired; eMAC_INIT_STATUS_TYPE xMacInitStatus; BaseType_t xEMACIndex; - UBaseType_t uxMACEntry; + MacFilteringData_t xMacFilteringData; } EMACData_t; */ /* TODO: need a data structure to assist in adding/removing allowed addresses */ @@ -293,18 +372,19 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa #ifdef niEMAC_STM32HX static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); #endif +static BaseType_t prvPhyInit( ETH_TypeDef * const pxEthInstance, EthernetPhy_t * pxPhyObject ); static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); /* MAC Filtering Helpers */ static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ); static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ); -static void prvHAL_ETH_SetDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex, const uint8_t * const pucMACAddr ); -static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex ); -static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); -static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); -static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ); -static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ); -static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex, const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex ); +static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); +static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); +static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ); +static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex ); +static void prvRemoveDestMACAddrHash( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); /* EMAC Helpers */ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ); @@ -316,6 +396,18 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes /* Network Interface Definition */ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); +/* Reimplemented HAL Functions */ +static void prvHAL_ETH_SetHashTable( ETH_TypeDef * const pxEthInstance ); +static BaseType_t prvHAL_ETH_ReadPHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t * pulRegValue ); +static BaseType_t prvHAL_ETH_WritePHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t ulRegValue ); + +/* Debugging */ +#if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) + static void prvHAL_RX_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); + static void prvHAL_DMA_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); + static void prvHAL_MAC_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); +#endif + /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Static Variable Declarations */ @@ -326,12 +418,14 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net static ETH_HandleTypeDef xEthHandle; -/* static ETH_TxPacketConfig xTxConfig; */ - static EthernetPhy_t xPhyObject; -static TaskHandle_t xEMACTaskHandle = NULL; +#if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) + static lan8742_Object_t xLan8742aObject; + static dp83848_Object_t xDp83848Object; +#endif +static TaskHandle_t xEMACTaskHandle = NULL; static SemaphoreHandle_t xTxMutex = NULL, xTxDescSem = NULL; static BaseType_t xSwitchRequired = pdFALSE; @@ -339,8 +433,6 @@ static BaseType_t xSwitchRequired = pdFALSE; static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMacEthInit; /* Src Mac Matching */ -/* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ -static const uint32_t xSrcMatchRegOffets[ niEMAC_MAC_SRC_MATCH_COUNT ] = { ETH_MAC_ADDRESS1, ETH_MAC_ADDRESS2, ETH_MAC_ADDRESS3 }; static uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ] = { 0U }; static uint8_t uxMACEntryIndex = 0; @@ -356,11 +448,11 @@ static uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ] = { 0U }; static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - BaseType_t xResult = pdTRUE; + BaseType_t xResult = pdFALSE; - if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + if( prvHAL_ETH_ReadPHYRegister( xEthHandle.Instance, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) != pdPASS ) { - xResult = pdFALSE; + xResult = pdTRUE; } return xResult; @@ -370,11 +462,11 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) { - BaseType_t xResult = pdTRUE; + BaseType_t xResult = pdFALSE; - if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) + if( prvHAL_ETH_WritePHYRegister( xEthHandle.Instance, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) != pdPASS ) { - xResult = pdFALSE; + xResult = pdTRUE; } return xResult; @@ -427,9 +519,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacPhyInit: - vPhyInitialise( pxPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); - - if( xPhyDiscover( pxPhyObject ) == 0 ) + if( prvPhyInit( pxEthHandle->Instance, pxPhyObject ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyInit failed\n" ) ); break; @@ -459,7 +549,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacEthStart: - if( HAL_ETH_GetState( pxEthHandle ) != HAL_ETH_STATE_STARTED ) + if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) { if( HAL_ETH_Start_IT( pxEthHandle ) != HAL_OK ) { @@ -519,33 +609,22 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - if( ( xMacInitStatus != eMacInitComplete ) || ( HAL_ETH_GetState( pxEthHandle ) != HAL_ETH_STATE_STARTED ) ) + if( ( xMacInitStatus != eMacInitComplete ) || ( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Interface Not Started\n" ) ); break; } - /* static ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ] = { 0 }; */ - - static ETH_TxPacketConfig xTxConfig = { - .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, - .Length = 0U, - .TxBuffer = NULL, - /* .SrcAddrCtrl = ETH_SRC_ADDR_CONTROL_DISABLE, */ + ETH_TxPacketConfig xTxConfig = { .CRCPadCtrl = ETH_CRC_PAD_INSERT, - .ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC, - .MaxSegmentSize = ipconfigTCP_MSS, - .PayloadLen = 0U, - .TCPHeaderLen = 0U, - .VlanTag = 0U, - /* .VlanCtrl = ETH_VLAN_DISABLE, */ - .InnerVlanTag = 0U, - /* .InnerVlanCtrl = ETH_INNER_VLAN_DISABLE, */ - .pData = NULL, + .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, }; #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; + #else + xTxConfig.ChecksumCtrl = ETH_CHECKSUM_DISABLE; #endif const EthernetHeader_t * const pxEthHeader = ( const EthernetHeader_t * const ) pxDescriptor->pucEthernetBuffer; @@ -553,8 +632,6 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N { #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) const IPPacket_t * const pxIPPacket = ( const IPPacket_t * const ) pxDescriptor->pucEthernetBuffer; - /* ProtocolPacket_t * const pxIPPacket = ( ProtocolPacket_t * const ) pxDescriptor->pucEthernetBuffer; */ - /* ProtocolHeaders_t * const pxIPPacket = ( ProtocolHeaders_t * const ) pxDescriptor->pucEthernetBuffer; */ if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_ICMP ) { @@ -573,6 +650,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) TCPPacket_t * const pxTCPPacket = ( TCPPacket_t * const ) pxDescriptor->pucEthernetBuffer; /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) + xTxConfig.MaxSegmentSize = ipconfigTCP_MSS; xTxConfig.PayloadLen = pxDescriptor->xDataLength; xTxConfig.TCPHeaderLen = ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ); xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; @@ -646,6 +724,12 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.TxBuffer = &xTxBuffer; xTxConfig.Length = xTxBuffer.len; + /* TODO: Queue Tx Output? */ + /* if( xQueueSendToBack( xTxQueue, pxDescriptor, 0 ) != pdPASS ) + { + xReleaseAfterSend = pdFALSE; + } */ + if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: No Descriptors Available\n" ) ); @@ -656,10 +740,20 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Process Busy\n" ) ); ( void ) xSemaphoreGive( xTxDescSem ); - /* TODO: Can we queue it? */ break; } + #if defined( niEMAC_CACHEABLE ) + if( niEMAC_CACHE_MAINTENANCE ) + { + const uintptr_t uxDataStart = ( uintptr_t ) xTxBuffer.buffer; + const uintptr_t uxLineStart = uxDataStart & ~niEMAC_DATA_ALIGNMENT_MASK; + const ptrdiff_t uxDataOffset = uxDataStart - uxLineStart; + const size_t uxLength = xTxBuffer.len + uxDataOffset; + SCB_CleanDCache_by_Addr( ( uint32_t * ) uxLineStart, uxLength ); + } + #endif + if( HAL_ETH_Transmit_IT( pxEthHandle, &xTxConfig ) == HAL_OK ) { /* Released later in deferred task by calling HAL_ETH_ReleaseTxPacket */ @@ -669,9 +763,10 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N else { ( void ) xSemaphoreGive( xTxDescSem ); - configASSERT( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ); - niEMAC_DEBUG( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_BUSY ) != 0, "xNetworkInterfaceOutput: Tx Busy\n" ); - /* Add to queue? */ + configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); + /* Should be impossible if semaphores are correctly implemented */ + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) == 0 ); + } ( void ) xSemaphoreGive( xTxMutex ); @@ -692,17 +787,17 @@ static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uin ETH_HandleTypeDef * pxEthHandle = &xEthHandle; /* TODO: group address filtering with Mask Byte Control */ - BaseType_t xResult = prvAddDestMACAddrMatch( pxEthHandle, pucMacAddress ); + BaseType_t xResult = prvAddDestMACAddrMatch( pxEthHandle->Instance, pucMacAddress ); if( xResult == pdFALSE ) { const uint8_t ucHashIndex = prvGetMacHashIndex( pucMacAddress ); - xResult = prvSetNewDestMACAddrMatch( pxEthHandle, ucHashIndex, pucMacAddress ); + xResult = prvSetNewDestMACAddrMatch( pxEthHandle->Instance, ucHashIndex, pucMacAddress ); if( xResult == pdFALSE ) { - prvAddDestMACAddrHash( pxEthHandle, ucHashIndex ); + prvAddDestMACAddrHash( pxEthHandle->Instance, ucHashIndex ); } } } @@ -713,11 +808,11 @@ static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; - const BaseType_t xResult = prvRemoveDestMACAddrMatch( pxEthHandle, pucMacAddress ); + const BaseType_t xResult = prvRemoveDestMACAddrMatch( pxEthHandle->Instance, pucMacAddress ); if( xResult == pdFALSE ) { - prvRemoveDestMACAddrHash( pxEthHandle, pucMacAddress ); + prvRemoveDestMACAddrHash( pxEthHandle->Instance, pucMacAddress ); } } @@ -736,7 +831,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; - if( ( xMacInitStatus == eMacInitComplete ) && ( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ) ) + if( ( xMacInitStatus == eMacInitComplete ) && ( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) ) { while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { @@ -816,8 +911,8 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrEth ) != 0 ) { - configASSERT( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_PARAM ) == 0 ); - if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) + configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Recover from critical error */ ( void ) HAL_ETH_Init( pxEthHandle ); @@ -834,12 +929,12 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) { if( prvGetPhyLinkStatus( pxInterface ) != pdFALSE ) { - if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) + if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Recover from critical error */ ( void ) HAL_ETH_Init( pxEthHandle ); } - if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_READY ) + if( pxEthHandle->gState == HAL_ETH_STATE_READY ) { /* Link was down or critical error occurred */ if( prvMacUpdateConfig( pxEthHandle, pxPhyObject ) != pdFALSE ) @@ -946,7 +1041,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte pxEthHandle->Init.MediaInterface = ipconfigIS_ENABLED( niEMAC_USE_RMII ) ? HAL_ETH_RMII_MODE : HAL_ETH_MII_MODE; pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; - configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); + /* configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); */ configASSERT( pxEthHandle->Init.RxBuffLen % 4U == 0 ); #if ( defined( niEMAC_STM32FX ) && defined( ETH_RX_BUF_SIZE ) ) configASSERT( pxEthHandle->Init.RxBuffLen == ETH_RX_BUF_SIZE ); @@ -976,24 +1071,12 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) { - /* xTxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; - xTxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD; - #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) - xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_CSUM; - xTxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; - #else - xTxConfig.ChecksumCtrl = ETH_CHECKSUM_DISABLE; - #endif */ - ETH_MACConfigTypeDef xMACConfig; ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); - #if defined( niEMAC_STM32FX ) - xMACConfig.AutomaticPadCRCStrip = ENABLE; - xMACConfig.RetryTransmission = ENABLE; - #elif defined( niEMAC_STM32HX ) - xMACConfig.CRCStripTypePacket = DISABLE; - #endif + xMACConfig.CRCStripTypePacket = DISABLE; + xMACConfig.AutomaticPadCRCStrip = ENABLE; + xMACConfig.RetryTransmission = ENABLE; ( void ) HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ); ETH_DMAConfigTypeDef xDMAConfig; @@ -1012,11 +1095,9 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte #if defined( niEMAC_STM32HX ) prvInitPacketFilter( pxEthHandle, pxInterface ); - /* #if ipconfigIS_ENABLED( niEMAC_ARP_OFFLOAD ) - HAL_ETHEx_DisableARPOffload( pxEthHandle ); - HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulAddress ); - HAL_ETHEx_EnableARPOffload( pxEthHandle ); - #endif */ + /* HAL_ETHEx_DisableARPOffload( pxEthHandle ); + HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulSourceIPAddress ); + HAL_ETHEx_EnableARPOffload( pxEthHandle ); */ #endif prvInitMacAddresses( pxEthHandle, pxInterface ); @@ -1028,21 +1109,27 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte if( xResult == pdTRUE ) { #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) - if( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) + if( niEMAC_CACHE_ENABLED ) { #if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) configASSERT( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ); #else configASSERT( pdFALSE ); #endif + /* _FLD2VAL( SCB_CCSIDR_LINESIZE, SCB->CCSIDR ) */ } #endif - const uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8 - configPRIO_BITS ); + #ifdef configPRIO_BITS + const uint32_t ulPrioBits = configPRIO_BITS; + #else + const uint32_t ulPrioBits = __NVIC_PRIO_BITS; + #endif + const uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8U - ulPrioBits ); if( ulPriority < configMAX_SYSCALL_INTERRUPT_PRIORITY ) { FreeRTOS_debug_printf( ( "prvEthConfigInit: Incorrectly set ETH_IRQn priority\n" ) ); - NVIC_SetPriority( ETH_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY >> ( 8 - configPRIO_BITS ) ); + NVIC_SetPriority( ETH_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY >> ( 8U - ulPrioBits ) ); } if( NVIC_GetEnableIRQ( ETH_IRQn ) == 0 ) { @@ -1078,12 +1165,7 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa xFilterConfig.HachOrPerfectFilter = ENABLE; xFilterConfig.SrcAddrFiltering = DISABLE; xFilterConfig.SrcAddrInverseFiltering = DISABLE; - #ifdef niEMAC_STM32FX - /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ - xFilterConfig.ControlPacketsFilter = ETH_MACFFR_PCF_BlockAll; - #else - xFilterConfig.ControlPacketsFilter = ETH_CTRLPACKETS_BLOCK_ALL; - #endif + xFilterConfig.ControlPacketsFilter = ETH_CTRLPACKETS_BLOCK_ALL; xFilterConfig.BroadcastFilter = ENABLE; xFilterConfig.PassAllMulticast = DISABLE; xFilterConfig.DestAddrInverseFiltering = DISABLE; @@ -1126,128 +1208,195 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI { HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); - if( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) ) + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) { - ETH_MACConfigTypeDef xMACConfig; - ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - if( xMACConfig.ChecksumOffload != ENABLE ) - { - /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum - Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ - xMACConfig.ChecksumOffload = ENABLE; - ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); - } - configASSERT( xMACConfig.ChecksumOffload == ENABLE ); - - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + const uint8_t ucFilterCount = _FLD2VAL( ETH_MACHWF1R_L3L4FNUM, pxEthHandle->Instance->MACHWF1R ); + if( ucFilterCount > 0 ) { - ETH_L3FilterConfigTypeDef xL3FilterConfig; - - /* Filter out all possibilities if frame type is disabled */ - if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + if( xMACConfig.ChecksumOffload != ENABLE ) { - /* Block IPv4 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; - xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum + Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ + xMACConfig.ChecksumOffload = ENABLE; + ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); } - if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) ) + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) { - /* Block IPv6 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - } + ETH_L3FilterConfigTypeDef xL3FilterConfig; - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + /* Filter out all possibilities if frame type is disabled */ + if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) - { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; - xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - } + /* Block IPv4 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; + xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); } - else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + + if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) && ( ucFilterCount > 1 ) ) + { + /* Block IPv6 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } + + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ) + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; + xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + } + } + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + { + if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) && ( ucFilterCount > 1 ) ) + { + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + } } } - } - } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ + } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) - { - /* TODO: Let user to block certain port numbers */ - /* TODO: Live updated in task based on active sockets? */ - ETH_L4FilterConfigTypeDef xL4FilterConfig; - - /* Always allow all UDP */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.SourcePort = 0U; - xL4FilterConfig.DestinationPort = 0U; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - - if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) + if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) { - /* Block TCP if it is disabled */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.SourcePort = 0xFFFFU; - xL4FilterConfig.DestinationPort = 0xFFFFU; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + /* TODO: Let user to block certain port numbers */ + /* TODO: Live updated in task based on active sockets? */ + ETH_L4FilterConfigTypeDef xL4FilterConfig; + + /* Always allow all UDP */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.SourcePort = 0U; + xL4FilterConfig.DestinationPort = 0U; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) + { + /* Block TCP if it is disabled */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.SourcePort = 0xFFFFU; + xL4FilterConfig.DestinationPort = 0xFFFFU; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + } } - } - HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); - - } /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); + } + } + #endif /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ } #endif /* ifdef niEMAC_STM32HX */ /*---------------------------------------------------------------------------*/ +static BaseType_t prvPhyInit( ETH_TypeDef * const pxEthInstance, EthernetPhy_t * pxPhyObject ) +{ + BaseType_t xResult = pdFAIL; + + vPhyInitialise( pxPhyObject, ( xApplicationPhyReadHook_t ) prvPhyReadReg, ( xApplicationPhyWriteHook_t ) prvPhyWriteReg ); + + if( xPhyDiscover( pxPhyObject ) != 0 ) + { + #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) + for( size_t uxCount = 0; uxCount < pxPhyObject->xPortCount; ++uxCount ) + { + if( pxPhyObject->ulPhyIDs[ uxCount ] == PHY_ID_LAN8742A ) + { + xLan8742aObject.DevAddr = pxPhyObject->ucPhyIndexes[ uxCount ]; + lan8742_IOCtx_t xLan8742aControl = { + .Init = NULL, + .DeInit = NULL, + .WriteReg = ( lan8742_WriteReg_Func ) &prvPhyWriteReg, + .ReadReg = ( lan8742_ReadReg_Func ) &prvPhyReadReg, + #if ( INCLUDE_vTaskDelay == 1 ) + .GetTick = ( lan8742_GetTick_Func ) &vTaskDelay, + #else + .GetTick = ( lan8742_GetTick_Func ) &HAL_GetTick, + #endif + }; + ( void ) LAN8742_RegisterBusIO( &xLan8742aObject, &xLan8742aControl ); + xLan8742aObject.Is_Initialized = 1U; + if( LAN8742_EnableIT( &xLan8742aObject, LAN8742_LINK_DOWN_IT ) == LAN8742_STATUS_OK ) + { + pxEthInstance->MACIER |= ETH_MACIER_PHYIE; + } + break; + } + else if( pxPhyObject->ulPhyIDs[ uxCount ] == PHY_ID_DP83848I ) + { + xDp83848Object.DevAddr = pxPhyObject->ucPhyIndexes[ uxCount ]; + dp83848_IOCtx_t xDp83848Control = { + .Init = NULL, + .DeInit = NULL, + .WriteReg = ( dp83848_WriteReg_Func ) &prvPhyWriteReg, + .ReadReg = ( dp83848_ReadReg_Func ) &prvPhyReadReg, + #if ( INCLUDE_vTaskDelay == 1 ) + .GetTick = ( dp83848_GetTick_Func ) &vTaskDelay, + #else + .GetTick = ( dp83848_GetTick_Func ) &HAL_GetTick, + #endif + }; + ( void ) DP83848_RegisterBusIO( &xDp83848Object, &xDp83848Control ); + xDp83848Object.Is_Initialized = 1U; + if( DP83848_EnableIT( &xDp83848Object, DP83848_LINK_DOWN_IT ) == DP83848_STATUS_OK ) + { + pxEthInstance->MACIER |= ETH_MACIER_PHYIE; + } + break; + } + } + #endif /* if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) */ + + xResult = pdPASS; + } + + return xResult; +} + static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -1273,8 +1422,8 @@ static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface }; #if ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) - pxPhyObject->xPhyPreferences.ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10; - pxPhyObject->xPhyPreferences.ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + pxPhyObject->xPhyPreferences.ucSpeed = xPhyProperties.ucSpeed; + pxPhyObject->xPhyPreferences.ucDuplex = xPhyProperties.ucDuplex; #endif if( xPhyConfigure( pxPhyObject, &xPhyProperties ) == 0 ) @@ -1340,41 +1489,33 @@ static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ) /*---------------------------------------------------------------------------*/ /* Needed since HAL Driver only provides source matching */ -static void prvHAL_ETH_SetDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex, const uint8_t * const pucMACAddr ) +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex, const uint8_t * const pucMACAddr ) { - /* Get mac addr high reg offset */ - const uint32_t macaddrhr = ((uint32_t) &(pxEthHandle->Instance->MACA0HR) + xSrcMatchRegOffets[ ucIndex ]); - /* Get mac addr low reg offset */ - const uint32_t macaddrlr = ((uint32_t) &(pxEthHandle->Instance->MACA0LR) + xSrcMatchRegOffets[ ucIndex ]); - - /* Set MAC addr bits 32 to 47 */ - (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pucMACAddr[5]) << 8) | (uint32_t)pucMACAddr[4]); - /* Set MAC addr bits 0 to 31 */ - (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pucMACAddr[3]) << 24) | ((uint32_t)(pucMACAddr[2]) << 16) | - ((uint32_t)(pucMACAddr[1]) << 8) | (uint32_t)pucMACAddr[0]); - - /* Enable address and set source address bit */ - (*(__IO uint32_t *)macaddrhr) |= ETH_MACA1HR_AE; + configASSERT( ucIndex < niEMAC_MAC_SRC_MATCH_COUNT ); + const uint32_t ulMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); + const uint32_t ulMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); + + /* MACA0HR/MACA0LR reserved for the primary MAC-address. */ + const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); + const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); + ( * ( __IO uint32_t * ) ulMacRegHigh ) = ETH_MACA1HR_AE | ulMacAddrHigh; + ( * ( __IO uint32_t * ) ulMacRegLow ) = ulMacAddrLow; } /*---------------------------------------------------------------------------*/ -static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucIndex ) +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex ) { - /* Get mac addr high reg offset */ - const uint32_t macaddrhr = ((uint32_t) &(pxEthHandle->Instance->MACA0HR) + xSrcMatchRegOffets[ ucIndex ]); - /* Get mac addr low reg offset */ - const uint32_t macaddrlr = ((uint32_t) &(pxEthHandle->Instance->MACA0LR) + xSrcMatchRegOffets[ ucIndex ]); - - /* Clears MAC addr bits 32 to 47 and ETH_MACAHR_AE */ - (*(__IO uint32_t *)macaddrhr) = 0; - /* Clears MAC addr bits 0 to 31 */ - (*(__IO uint32_t *)macaddrlr) = 0; + configASSERT( ucIndex < niEMAC_MAC_SRC_MATCH_COUNT ); + const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); + const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); + ( * ( __IO uint32_t * ) ulMacRegHigh ) = 0U; + ( * ( __IO uint32_t * ) ulMacRegLow ) = 0U; } /*---------------------------------------------------------------------------*/ -static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; @@ -1383,15 +1524,19 @@ static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const { if( ucSrcMatchCounters[ ucIndex ] > 0U ) { - const uint32_t ulNewMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); - const uint32_t ulNewMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); + /* ETH_MACA1HR_MBC - Group Address Filtering */ + const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); + const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); - const uint32_t ulMacAddrHigh = ( ( ( uint32_t ) &( pxEthHandle->Instance->MACA0HR ) + xSrcMatchRegOffets[ ucIndex ] ) & 0x0000FFFFU ); - const uint32_t ulMacAddrLow = ( ( uint32_t ) &( pxEthHandle->Instance->MACA0LR ) + xSrcMatchRegOffets[ ucIndex ]); + const uint32_t ulMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); + const uint32_t ulMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); - if( ( ulNewMacAddrHigh == ulMacAddrHigh ) && ( ulNewMacAddrLow == ulMacAddrLow ) ) + if( ( ulMacRegHigh == ulMacAddrHigh ) && ( ulMacRegLow == ulMacAddrLow ) ) { - ++( ucSrcMatchCounters[ ucIndex ] ); + if( ucSrcMatchCounters[ ucIndex ] < UINT8_MAX ) + { + ++( ucSrcMatchCounters[ ucIndex ] ); + } xResult = pdTRUE; break; } @@ -1407,7 +1552,7 @@ static BaseType_t prvAddDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const /*---------------------------------------------------------------------------*/ -static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; @@ -1416,19 +1561,20 @@ static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, co { if( ucSrcMatchCounters[ ucIndex ] > 0U ) { - const uint32_t ulNewMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); - const uint32_t ulNewMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); + /* ETH_MACA1HR_MBC - Group Address Filtering */ + const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); + const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); - const uint32_t ulMacAddrHigh = ( ( ( uint32_t ) &( pxEthHandle->Instance->MACA0HR ) + xSrcMatchRegOffets[ ucIndex ] ) & 0x0000FFFFU ); - const uint32_t ulMacAddrLow = ( ( uint32_t ) &( pxEthHandle->Instance->MACA0LR ) + xSrcMatchRegOffets[ ucIndex ]); + const uint32_t ulMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); + const uint32_t ulMacAddrLow = ( pucMACAddr[ 3 ] << 24 ) | ( pucMACAddr[ 2 ] << 16 ) | ( pucMACAddr[ 1 ] << 8 ) | ( pucMACAddr[ 0 ] ); - if( ( ulNewMacAddrHigh == ulMacAddrHigh ) && ( ulNewMacAddrLow == ulMacAddrLow ) ) + if( ( ulMacRegHigh == ulMacAddrHigh ) && ( ulMacRegLow == ulMacAddrLow ) ) { if( ucSrcMatchCounters[ ucIndex ] < UINT8_MAX ) { if( --( ucSrcMatchCounters[ ucIndex ] ) == 0 ) { - prvHAL_ETH_ClearDestMACAddrMatch( pxEthHandle, ucIndex ); + prvHAL_ETH_ClearDestMACAddrMatch( pxEthInstance, ucIndex ); } } @@ -1443,7 +1589,7 @@ static BaseType_t prvRemoveDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, co /*---------------------------------------------------------------------------*/ -static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ) +static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; @@ -1451,7 +1597,7 @@ static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, ui { if( ucAddrHashCounters[ ucHashIndex ] == 0U ) { - prvHAL_ETH_SetDestMACAddrMatch( pxEthHandle, uxMACEntryIndex, pucMACAddr ); + prvHAL_ETH_SetDestMACAddrMatch( pxEthInstance, uxMACEntryIndex, pucMACAddr ); ucSrcMatchCounters[ uxMACEntryIndex ] = 1U; xResult = pdTRUE; } @@ -1462,7 +1608,7 @@ static BaseType_t prvSetNewDestMACAddrMatch( ETH_HandleTypeDef * pxEthHandle, ui /*---------------------------------------------------------------------------*/ -static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ) +static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex ) { if( ucAddrHashCounters[ ucHashIndex ] == 0 ) { @@ -1475,7 +1621,7 @@ static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHa ulHashTable[ 0 ] |= ( 1U << ucHashIndex ); } - ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + prvHAL_ETH_SetHashTable( pxEthInstance ); } if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) @@ -1486,7 +1632,7 @@ static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHa /*---------------------------------------------------------------------------*/ -static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +static void prvRemoveDestMACAddrHash( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) { const uint8_t ucHashIndex = prvGetMacHashIndex( pucMACAddr ); @@ -1494,7 +1640,7 @@ static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uin { if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) { - if( --ucAddrHashCounters[ ucHashIndex ] == 0 ) + if( --( ucAddrHashCounters[ ucHashIndex ] ) == 0 ) { if( ucHashIndex & 0x20U ) { @@ -1505,7 +1651,7 @@ static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uin ulHashTable[ 0 ] &= ~( 1U << ucHashIndex ); } - ( void ) HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); + prvHAL_ETH_SetHashTable( pxEthInstance ); } } } @@ -1542,7 +1688,7 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP { BaseType_t xResult = pdFALSE; - if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_STARTED ) + if( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) { ( void ) HAL_ETH_Stop_IT( pxEthHandle ); } @@ -1563,12 +1709,12 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP xResult = pdTRUE; } - #if ipconfigIS_ENABLED( niEMAC_AUTO_LOW_POWER ) + /* #if ipconfigIS_ENABLED( niEMAC_AUTO_LOW_POWER ) if( ( pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE ) && ( xMACConfig.DuplexMode == ETH_FULLDUPLEX_MODE ) && ( xMACConfig.Speed == ETH_SPEED_100M ) ) { HAL_ETHEx_EnterLPIMode( pxEthHandle, ENABLE, DISABLE ); } - #endif + #endif */ return xResult; } @@ -1620,41 +1766,103 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes break; } - uint32_t ulErrorCode = 0; - ( void ) HAL_ETH_GetRxDataErrorCode( &xEthHandle, &ulErrorCode ); - if( ulErrorCode != 0 ) + if( usLength > pxDescriptor->xDataLength ) { iptraceETHERNET_RX_EVENT_LOST(); - FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); + FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); break; } - /* if( ( ulErrorCode & ETH_DRIBBLE_BIT_ERROR ) != 0 ) - if( ( ulErrorCode & ETH_RECEIVE_ERROR ) != 0 ) - if( ( ulErrorCode & ETH_RECEIVE_OVERFLOW ) != 0 ) - if( ( ulErrorCode & ETH_WATCHDOG_TIMEOUT ) != 0 ) - if( ( ulErrorCode & ETH_GIANT_PACKET ) != 0 ) - if( ( ulErrorCode & ETH_CRC_ERROR ) != 0 ) */ - - if( usLength > niEMAC_DATA_BUFFER_SIZE ) + + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + uint32_t ulErrorCode = 0; + ( void ) HAL_ETH_GetRxDataErrorCode( pxEthHandle, &ulErrorCode ); + if( ulErrorCode != 0 ) { + #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) + prvHAL_RX_ErrorCallback( pxEthHandle ); + #endif iptraceETHERNET_RX_EVENT_LOST(); - FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet size overflow\n" ) ); + FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); break; } - /* TODO: Should we do this even if it is handled in hardware too? */ #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { + iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Frame discarded\n" ) ); break; } #endif - /* TODO: Create a eConsiderPacketForProcessing */ #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #ifdef niEMAC_STM32HX + const ETH_DMADescTypeDef * const ulRxDesc = ( const ETH_DMADescTypeDef * const ) pxEthHandle->RxDescList.RxDesc[ pxEthHandle->RxDescList.RxDescIdx ]; + + const uint32_t ulRxDesc1 = ulRxDesc->DESC1; + + if( ( ulRxDesc1 & ETH_CHECKSUM_IP_PAYLOAD_ERROR ) != 0 ) + { + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + + if( ( ulRxDesc1 & ETH_CHECKSUM_IP_HEADER_ERROR ) != 0 ) + { + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + + if( ( ulRxDesc1 & ETH_IP_HEADER_IPV4 ) != 0 ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /* prvAllowIPPacketIPv4(); */ + #endif + } + else if( ( ulRxDesc1 & ETH_IP_HEADER_IPV6 ) != 0 ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /* prvAllowIPPacketIPv6(); */ + #endif + } + + const uint32_t ulPacketType = ulRxDesc1 & ETH_DMARXNDESCWBF_PT; + if( ulPacketType == ETH_IP_PAYLOAD_UNKNOWN ) + { + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + else if( ulPacketType == ETH_IP_PAYLOAD_UDP ) + { + /* prvProcessUDPPacket(); */ + } + else if( ulPacketType == ETH_IP_PAYLOAD_ICMPN ) + { + #if ipconfigIS_DISABLED( ipconfigREPLY_TO_INCOMING_PINGS ) && ipconfigIS_DISABLED( ipconfigSUPPORT_OUTGOING_PINGS ) + iptraceETHERNET_RX_EVENT_LOST(); + break; + #else + /* ProcessICMPPacket(); */ + #endif + } + else if( ulPacketType == ETH_IP_PAYLOAD_TCP ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_TCP ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) + /* xProcessReceivedTCPPacket() */ + #endif + } + #endif + + /* TODO: Create a eConsiderPacketForProcessing */ if( eConsiderPacketForProcessing( pxDescriptor->pucEthernetBuffer ) != eProcessBuffer ) { + iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet discarded\n" ) ); break; } @@ -1677,8 +1885,30 @@ void ETH_IRQHandler( void ) { traceISR_ENTER(); + ETH_HandleTypeDef * pxEthHandle = &xEthHandle; + xSwitchRequired = pdFALSE; - HAL_ETH_IRQHandler( &xEthHandle ); + HAL_ETH_IRQHandler( pxEthHandle ); + + #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) + if( ( pxEthHandle->Instance->MACIER & ETH_MACIER_PHYIE ) != 0 ) + { + if( xLan8742aObject.Is_Initialized != 0 ) + { + if( LAN8742_GetITStatus( &xLan8742aObject, LAN8742_LINK_DOWN_IT ) ) + { + LAN8742_ClearIT( &xLan8742aObject, LAN8742_LINK_DOWN_IT ); + } + } + if( xDp83848Object.Is_Initialized != 0 ) + { + if( DP83848_GetITStatus( &xDp83848Object, DP83848_LINK_DOWN_IT ) ) + { + DP83848_ClearIT( &xDp83848Object, DP83848_LINK_DOWN_IT ); + } + } + } + #endif /* if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) */ portYIELD_FROM_ISR( xSwitchRequired ); } @@ -1689,49 +1919,36 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { eMAC_IF_EVENT eErrorEvents = eMacEventNone; - if( HAL_ETH_GetState( pxEthHandle ) == HAL_ETH_STATE_ERROR ) + if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Fatal bus error occurred */ eErrorEvents |= eMacEventErrEth; } - if( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_DMA ) != 0 ) + if( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_DMA ) != 0 ) { eErrorEvents |= eMacEventErrDma; - /* if( pxEthHandle->DMAErrorCode & ETH_DMA_TX_PROCESS_STOPPED_FLAG ) */ - #ifdef niEMAC_STM32FX - if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMASR_TBUS ) != 0 ) - { - eErrorEvents |= eMacEventErrTx; - } - - if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMASR_RBUS ) != 0 ) - { - eErrorEvents |= eMacEventErrRx; - } - #elif defined( niEMAC_STM32HX ) - if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMACSR_TBU ) != 0 ) - { - eErrorEvents |= eMacEventErrTx; - } - - if( ( HAL_ETH_GetDMAError( pxEthHandle ) & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) - { - eErrorEvents |= eMacEventErrRx; - } + const uint32_t ulDmaError = pxEthHandle->DMAErrorCode; + #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) + prvHAL_DMA_ErrorCallback( pxEthHandle ); #endif + if( ( ulDmaError & ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) + { + eErrorEvents |= eMacEventErrTx; + } + + if( ( ulDmaError & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) + { + eErrorEvents |= eMacEventErrRx; + } } - if( ( HAL_ETH_GetError( pxEthHandle ) & HAL_ETH_ERROR_MAC ) != 0 ) + if( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC ) != 0 ) { - /*if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_RECEIVE_WATCHDOG_TIMEOUT ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_EXECESSIVE_COLLISIONS ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_LATE_COLLISIONS ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_EXECESSIVE_DEFERRAL ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_LOSS_OF_CARRIER ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_NO_CARRIER ) != 0 ) - if( ( HAL_ETH_GetMACError( pxEthHandle ) & ETH_TRANSMIT_JABBR_TIMEOUT ) != 0 )*/ eErrorEvents |= eMacEventErrMac; + #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) + prvHAL_MAC_ErrorCallback( pxEthHandle ); + #endif } if( ( xEMACTaskHandle != NULL ) && ( eErrorEvents != eMacEventNone ) ) @@ -1820,7 +2037,12 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { - /* TODO: Should any other checks be performed on pxBufferDescriptor? */ + #ifdef niEMAC_CACHEABLE + if( niEMAC_CACHE_MAINTENANCE ) + { + SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pxBufferDescriptor->pucEthernetBuffer, pxBufferDescriptor->xDataLength ); + } + #endif *ppucBuff = pxBufferDescriptor->pucEthernetBuffer; } else @@ -1855,6 +2077,12 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); + #ifdef niEMAC_CACHEABLE + if( niEMAC_CACHE_MAINTENANCE ) + { + SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pucBuff, usLength ); + } + #endif } else { @@ -1936,7 +2164,336 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /*---------------------------------------------------------------------------*/ /*===========================================================================*/ -/* Sample HAL_ETH_MspInit */ +/* Reimplemented HAL Functions */ +/*===========================================================================*/ +/*---------------------------------------------------------------------------*/ + +static void prvHAL_ETH_SetHashTable( ETH_TypeDef * const pxEthInstance ) +{ + #ifdef niEMAC_STM32FX + pxEthInstance->MACHTHR = ulHashTable[ 0 ]; + pxEthInstance->MACHTLR = ulHashTable[ 1 ]; + #elif defined( niEMAC_STM32HX ) + pxEthInstance->MACHT0R = ulHashTable[ 0 ]; + pxEthInstance->MACHT1R = ulHashTable[ 1 ]; + #endif +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvHAL_ETH_ReadPHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t * pulRegValue ) +{ + BaseType_t xResult = pdPASS; + + #ifdef niEMAC_STM32FX + uint32_t ulReg = pxEthInstance->MACMIIAR; + #elif defined( niEMAC_STM32HX ) + uint32_t ulReg = pxEthInstance->MACMDIOAR; + #endif + + #ifdef niEMAC_STM32FX + if( ( ulReg & ETH_MACMIIAR_MB ) != 0 ) + #elif defined( niEMAC_STM32HX ) + if( ( ulReg & ETH_MACMDIOAR_MB ) != 0 ) + #endif + { + xResult = pdFAIL; + } + else + { + #ifdef niEMAC_STM32FX + ulReg |= _VAL2FLD( ETH_MACMIIAR_PA, ulPhyAddr ); + ulReg |= _VAL2FLD( ETH_MACMIIAR_MR, ulPhyReg ); + ulReg &= ~ETH_MACMIIAR_MW; + ulReg |= ETH_MACMIIAR_MB; + pxEthInstance->MACMIIAR = ulReg; + #elif defined( niEMAC_STM32HX ) + ulReg |= _VAL2FLD( ETH_MACMDIOAR_PA, ulPhyAddr ); + ulReg |= _VAL2FLD( ETH_MACMDIOAR_RDA, ulPhyReg ); + MODIFY_REG( ulReg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD ); + ulReg |= ETH_MACMDIOAR_MB; + pxEthInstance->MACMDIOAR = ulReg; + #endif + + TimeOut_t xPhyWriteTimer; + vTaskSetTimeOutState( &xPhyWriteTimer ); + TickType_t xPhyWriteRemaining = pdMS_TO_TICKS( 0xFFFFU ); + #ifdef niEMAC_STM32FX + while( ( pxEthInstance->MACMIIAR & ETH_MACMIIAR_MB ) != 0 ) + #elif defined( niEMAC_STM32HX ) + while( ( pxEthInstance->MACMDIOAR & ETH_MACMDIOAR_MB ) != 0 ) + #endif + { + if( xTaskCheckForTimeOut( &xPhyWriteTimer, &xPhyWriteRemaining ) != pdFALSE ) + { + xResult = pdFAIL; + break; + } + else + { + vTaskDelay( pdMS_TO_TICKS( 1 ) ); + } + } + + #ifdef niEMAC_STM32FX + *pulRegValue = _FLD2VAL( ETH_MACMIIDR_MD, pxEthInstance->MACMIIDR ); + #elif defined( niEMAC_STM32HX ) + *pulRegValue = _FLD2VAL( ETH_MACMDIODR_MD, pxEthInstance->MACMDIODR ); + #endif + } + + return xResult; +} + +/*---------------------------------------------------------------------------*/ + +static BaseType_t prvHAL_ETH_WritePHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t ulRegValue ) +{ + BaseType_t xResult = pdPASS; + + #ifdef niEMAC_STM32FX + uint32_t ulReg = pxEthInstance->MACMIIAR; + #elif defined( niEMAC_STM32HX ) + uint32_t ulReg = pxEthInstance->MACMDIOAR; + #endif + + #ifdef niEMAC_STM32FX + if( ( ulReg & ETH_MACMIIAR_MB ) != 0 ) + #elif defined( niEMAC_STM32HX ) + if( ( ulReg & ETH_MACMDIOAR_MB ) != 0 ) + #endif + { + xResult = pdFAIL; + } + else + { + #ifdef niEMAC_STM32FX + ulReg |= _VAL2FLD( ETH_MACMIIAR_PA, ulPhyAddr ); + ulReg |= _VAL2FLD( ETH_MACMIIAR_MR, ulPhyReg ); + ulReg |= ETH_MACMIIAR_MW; + ulReg |= ETH_MACMIIAR_MB; + pxEthInstance->MACMIIDR = _VAL2FLD( ETH_MACMIIDR_MD, ( uint16_t ) ulRegValue ); + pxEthInstance->MACMIIAR = ulReg; + #elif defined( niEMAC_STM32HX ) + ulReg |= _VAL2FLD( ETH_MACMDIOAR_PA, ulPhyAddr ); + ulReg |= _VAL2FLD( ETH_MACMDIOAR_RDA, ulPhyReg ); + MODIFY_REG( ulReg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR ); + ulReg |= ETH_MACMDIOAR_MB; + pxEthInstance->MACMDIODR = _VAL2FLD( ETH_MACMDIODR_MD, ( uint16_t ) ulRegValue ); + pxEthInstance->MACMDIOAR = ulReg; + #endif + + TimeOut_t xPhyWriteTimer; + vTaskSetTimeOutState( &xPhyWriteTimer ); + TickType_t xPhyWriteRemaining = pdMS_TO_TICKS( 0xFFFFU ); + #ifdef niEMAC_STM32FX + while( ( pxEthInstance->MACMIIAR & ETH_MACMIIAR_MB ) != 0 ) + #elif defined( niEMAC_STM32HX ) + while( ( pxEthInstance->MACMDIOAR & ETH_MACMDIOAR_MB ) != 0 ) + #endif + { + if( xTaskCheckForTimeOut( &xPhyWriteTimer, &xPhyWriteRemaining ) != pdFALSE ) + { + xResult = pdFAIL; + break; + } + else + { + vTaskDelay( pdMS_TO_TICKS( 1 ) ); + } + } + } + + return xResult; +} + +/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* Debugging */ +/*===========================================================================*/ +/*---------------------------------------------------------------------------*/ + +#if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) + +static void prvHAL_RX_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) +{ + uint32_t ulErrorCode = 0; + ( void ) HAL_ETH_GetRxDataErrorCode( pxEthHandle, &ulErrorCode ); + if( ( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) && ( ( ulErrorCode & ETH_DRIBBLE_BIT_ERROR ) != 0 ) ) + { + static size_t uxRxDBError = 0; + ++uxRxDBError; + } + if( ( ulErrorCode & ETH_RECEIVE_ERROR ) != 0 ) + { + static size_t uxRxRcvError = 0; + ++uxRxRcvError; + } + if( ( ulErrorCode & ETH_RECEIVE_OVERFLOW ) != 0 ) + { + static size_t uxRxROError = 0; + ++uxRxROError; + } + if( ( ulErrorCode & ETH_WATCHDOG_TIMEOUT ) != 0 ) + { + static size_t uxRxWDTError = 0; + ++uxRxWDTError; + } + if( ( ulErrorCode & ETH_GIANT_PACKET ) != 0 ) + { + static size_t uxRxGPError = 0; + ++uxRxGPError; + } + if( ( ulErrorCode & ETH_CRC_ERROR ) != 0 ) + { + static size_t uxRxCRCError = 0; + ++uxRxCRCError; + } +} + +/*---------------------------------------------------------------------------*/ + +static void prvHAL_DMA_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) +{ + #ifdef niEMAC_STM32HX + { + const uint32_t ulDmaError = pxEthHandle->DMAErrorCode; + if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) != ETH_DMA_RX_NO_ERROR_FLAG ) + { + /* if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_DESC_READ_ERROR_FLAG ) + { + static size_t uxDmaRDRError = 0; + ++uxDmaRDRError; + } + else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_DESC_WRITE_ERROR_FLAG ) + { + static size_t uxDmaRDWError = 0; + ++uxDmaRDWError; + } + else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_BUFFER_READ_ERROR_FLAG ) + { + static size_t uxDmaRBRError = 0; + ++uxDmaRBRError; + } + else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_BUFFER_WRITE_ERROR_FLAG ) + { + static size_t uxDmaRBWError = 0; + ++uxDmaRBWError; + } */ + } + if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) != ETH_DMA_TX_NO_ERROR_FLAG ) + { + /* if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_DESC_READ_ERROR_FLAG ) + { + static size_t uxDmaTDRError = 0; + ++uxDmaTDRError; + } + else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_DESC_WRITE_ERROR_FLAG ) + { + static size_t uxDmaTDWError = 0; + ++uxDmaTDWError; + } + else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_BUFFER_READ_ERROR_FLAG ) + { + static size_t uxDmaTBRError = 0; + ++uxDmaTBRError; + } + else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_BUFFER_WRITE_ERROR_FLAG ) + { + static size_t uxDmaTBWError = 0; + ++uxDmaTBWError; + } */ + } + if( ( ulDmaError & ETH_DMA_CONTEXT_DESC_ERROR_FLAG ) != 0 ) + { + static size_t uxDmaCDError = 0; + ++uxDmaCDError; + } + if( ( ulDmaError & ETH_DMA_FATAL_BUS_ERROR_FLAG ) != 0 ) + { + static size_t uxDmaFBEError = 0; + ++uxDmaFBEError; + } + if( ( ulDmaError & ETH_DMA_EARLY_TX_IT_FLAG ) != 0 ) + { + static size_t uxDmaETIError = 0; + ++uxDmaETIError; + } + if( ( ulDmaError & ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG ) != 0 ) + { + static size_t uxDmaRWTError = 0; + ++uxDmaRWTError; + } + if( ( ulDmaError & ETH_DMA_RX_PROCESS_STOPPED_FLAG ) != 0 ) + { + static size_t uxDmaRPSError = 0; + ++uxDmaRPSError; + } + if( ( ulDmaError & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) + { + static size_t uxDmaRBUError = 0; + ++uxDmaRBUError; + } + if( ( ulDmaError & ETH_DMA_TX_PROCESS_STOPPED_FLAG ) != 0 ) + { + static size_t uxDmaTPSError = 0; + ++uxDmaTPSError; + } + } + #endif /* ifdef niEMAC_STM32HX */ +} + +/*---------------------------------------------------------------------------*/ + +static void prvHAL_MAC_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) +{ + #ifdef niEMAC_STM32HX + { + const uint32_t ulMacError = pxEthHandle->MACErrorCode; + if( ( ulMacError & ETH_RECEIVE_WATCHDOG_TIMEOUT ) != 0 ) + { + static size_t uxMacRWTError = 0; + ++uxMacRWTError; + } + if( ( ulMacError & ETH_EXECESSIVE_COLLISIONS ) != 0 ) + { + static size_t uxMacECError = 0; + ++uxMacECError; + } + if( ( ulMacError & ETH_LATE_COLLISIONS ) != 0 ) + { + static size_t uxMacLCError = 0; + ++uxMacLCError; + } + if( ( ulMacError & ETH_EXECESSIVE_DEFERRAL ) != 0 ) + { + static size_t uxMacEDError = 0; + ++uxMacEDError; + } + if( ( ulMacError & ETH_LOSS_OF_CARRIER ) != 0 ) + { + static size_t uxMacLOCError = 0; + ++uxMacLOCError; + } + if( ( ulMacError & ETH_NO_CARRIER ) != 0 ) + { + static size_t uxMacNCError = 0; + ++uxMacNCError; + } + if( ( ulMacError & ETH_TRANSMIT_JABBR_TIMEOUT ) != 0 ) + { + static size_t uxMacTJTError = 0; + ++uxMacTJTError; + } + } + #endif /* ifdef niEMAC_STM32HX */ +} + +#endif /* ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) */ + +/*---------------------------------------------------------------------------*/ +/*===========================================================================*/ +/* Sample HAL User Functions */ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ @@ -1947,9 +2504,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net * @param heth: ETH handle * @retval None */ -void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) +void HAL_ETH_MspInit( ETH_HandleTypeDef * pxEthHandle ) { - if( heth->Instance == ETH ) + if( pxEthHandle->Instance == ETH ) { /* Enable ETHERNET clock */ #ifdef niEMAC_STM32FX @@ -2010,66 +2567,66 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) GPIO_InitStructure.Pin = ETH_MDC_Pin; GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; - HAL_GPIO_Init(ETH_MDC_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_MDC_Port, &GPIO_InitStructure ); GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Pin = ETH_MDIO_Pin; - HAL_GPIO_Init(ETH_MDIO_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_MDIO_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RXD0_Pin; - HAL_GPIO_Init(ETH_RXD0_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RXD0_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RXD1_Pin; - HAL_GPIO_Init(ETH_RXD1_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RXD1_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TX_EN_Pin; - HAL_GPIO_Init(ETH_TX_EN_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TX_EN_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TXD0_Pin; - HAL_GPIO_Init(ETH_TXD0_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TXD0_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TXD1_Pin; - HAL_GPIO_Init(ETH_TXD1_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TXD1_Port, &GPIO_InitStructure ); - if( heth->Init.MediaInterface == HAL_ETH_RMII_MODE ) + if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) { GPIO_InitStructure.Pin = ETH_REF_CLK_Pin; - HAL_GPIO_Init(ETH_REF_CLK_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_REF_CLK_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_CRS_DV_Pin; - HAL_GPIO_Init(ETH_CRS_DV_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_CRS_DV_Port, &GPIO_InitStructure ); } - else if( heth->Init.MediaInterface == HAL_ETH_MII_MODE ) + else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) { GPIO_InitStructure.Pin = ETH_RX_CLK_Pin; - HAL_GPIO_Init(ETH_RX_CLK_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RX_CLK_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RX_ER_Pin; - HAL_GPIO_Init(ETH_RX_ER_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RX_ER_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RX_DV_Pin; - HAL_GPIO_Init(ETH_RX_DV_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RX_DV_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RXD2_Pin; - HAL_GPIO_Init(ETH_RXD2_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RXD2_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_RXD3_Pin; - HAL_GPIO_Init(ETH_RXD3_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_RXD3_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TX_CLK_Pin; - HAL_GPIO_Init(ETH_TX_CLK_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TX_CLK_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TXD2_Pin; - HAL_GPIO_Init(ETH_TXD2_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TXD2_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_TXD3_Pin; - HAL_GPIO_Init(ETH_TXD3_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_TXD3_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_COL_Pin; - HAL_GPIO_Init(ETH_COL_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_COL_Port, &GPIO_InitStructure ); GPIO_InitStructure.Pin = ETH_CRS_Pin; - HAL_GPIO_Init(ETH_CRS_Port, &GPIO_InitStructure); + HAL_GPIO_Init( ETH_CRS_Port, &GPIO_InitStructure ); } /* Enable the Ethernet global Interrupt */ @@ -2078,15 +2635,85 @@ void HAL_ETH_MspInit( ETH_HandleTypeDef * heth ) } } -#endif /* if 0 */ - -/*---------------------------------------------------------------------------*/ -/*===========================================================================*/ -/* Sample MPU Config */ -/*===========================================================================*/ /*---------------------------------------------------------------------------*/ -#if 0 +void HAL_ETH_MspDeInit( ETH_HandleTypeDef * pxEthHandle ) +{ + if( pxEthHandle->Instance == ETH ) + { + /* Peripheral clock disable */ + #ifdef niEMAC_STM32FX + __HAL_RCC_ETH_CLK_DISABLE(); + #elif defined( STM32H5 ) + __HAL_RCC_ETH_CLK_DISABLE(); + __HAL_RCC_ETHTX_CLK_DISABLE(); + __HAL_RCC_ETHRX_CLK_DISABLE(); + #elif defined( STM32H7) + __HAL_RCC_ETH1MAC_CLK_DISABLE(); + __HAL_RCC_ETH1TX_CLK_DISABLE(); + __HAL_RCC_ETH1RX_CLK_DISABLE(); + #endif + + /**ETH GPIO Configuration + Common Pins + ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin + ETH_MDIO ---------------------> + ETH_RXD0 ---------------------> + ETH_RXD1 ---------------------> + ETH_TX_EN --------------------> + ETH_TXD0 ---------------------> + ETH_TXD1 ---------------------> + + RMII Specific Pins + ETH_REF_CLK ------------------> + ETH_CRS_DV -------------------> + + MII Specific Pins + ETH_RX_CLK -------------------> + ETH_RX_ER --------------------> + ETH_RX_DV --------------------> + ETH_RXD2 ---------------------> + ETH_RXD3 ---------------------> + ETH_TX_CLK -------------------> + ETH_TXD2 ---------------------> + ETH_TXD3 ---------------------> + ETH_CRS ----------------------> + ETH_COL ----------------------> + */ + + HAL_GPIO_DeInit( ETH_MDC_Port, ETH_MDC_Pin ); + HAL_GPIO_DeInit( ETH_MDIO_Port, ETH_MDIO_Pin ); + HAL_GPIO_DeInit( ETH_RXD0_Port, ETH_RXD0_Pin ); + HAL_GPIO_DeInit( ETH_RXD1_Port, ETH_RXD1_Pin ); + HAL_GPIO_DeInit( ETH_TX_EN_Port, ETH_TX_EN_Pin ); + HAL_GPIO_DeInit( ETH_TXD0_Port, ETH_TXD0_Pin ); + HAL_GPIO_DeInit( ETH_TXD1_Port, ETH_TXD1_Pin ); + + if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) + { + HAL_GPIO_DeInit( ETH_REF_CLK_Port, ETH_REF_CLK_Pin ); + HAL_GPIO_DeInit( ETH_CRS_DV_Port, ETH_CRS_DV_Pin ); + } + else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) + { + HAL_GPIO_DeInit( ETH_RX_CLK_Port, ETH_RX_CLK_Pin ); + HAL_GPIO_DeInit( ETH_RX_ER_Port, ETH_RX_ER_Pin ); + HAL_GPIO_DeInit( ETH_RX_DV_Port, ETH_RX_DV_Pin ); + HAL_GPIO_DeInit( ETH_RXD2_Port, ETH_RXD2_Pin ); + HAL_GPIO_DeInit( ETH_RXD3_Port, ETH_RXD3_Pin ); + HAL_GPIO_DeInit( ETH_TX_CLK_Port, ETH_TX_CLK_Pin ); + HAL_GPIO_DeInit( ETH_TXD2_Port, ETH_TXD2_Pin ); + HAL_GPIO_DeInit( ETH_TXD3_Port, ETH_TXD3_Pin ); + HAL_GPIO_DeInit( ETH_COL_Port, ETH_COL_Pin ); + HAL_GPIO_DeInit( ETH_CRS_Port, ETH_CRS_Pin ); + } + + /* ETH interrupt Deinit */ + HAL_NVIC_DisableIRQ(ETH_IRQn); + } +} + +/*---------------------------------------------------------------------------*/ #if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) @@ -2098,7 +2725,7 @@ void MPU_Config(void) extern uint8_t __ETH_BUFFERS_START; - MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Enable = ipconfigIS_ENABLED( niEMAC_USE_MPU ) ? ENABLE : DISABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; From 400e46abde283c13467a7013c339138e808a00be Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 30 Jan 2024 01:51:26 -0500 Subject: [PATCH 50/68] remove testing code --- .../NetworkInterface/STM32/NetworkInterface.c | 768 +++--------------- 1 file changed, 134 insertions(+), 634 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index b69c5dbb09..008224473f 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -71,16 +71,6 @@ #error "Unknown STM32 Family for NetworkInterface" #endif -#if defined( STM32H5 ) || defined( STM32H7 ) - /* #ifdef LAN8742A_PHY_ADDRESS */ - #include "lan8742/lan8742.h" - /* #endif */ - - /* #ifdef DP83848_PHY_ADDRESS */ - #include "dp83848/dp83848.h" - /* #endif */ -#endif - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Config */ @@ -119,15 +109,6 @@ #define niEMAC_USE_MPU ipconfigENABLE -#ifdef niEMAC_STM32HX - #define niEMAC_AUTO_LOW_POWER ( ipconfigDISABLE && ipconfigIS_DISABLED( niEMAC_USE_RMII ) ) - #define niEMAC_TCP_SEGMENTATION ipconfigDISABLE - #define niEMAC_ARP_OFFLOAD ipconfigDISABLE - #define niEMAC_USE_PHY_INT ipconfigDISABLE -#endif - -#define niEMAC_DEBUG_ERROR ipconfigDISABLE - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Config Checks */ @@ -154,18 +135,6 @@ #error "Unsupported ipconfigNETWORK_MTU size for NetworkInterface" #endif -#if defined( niEMAC_STM32HX ) - - #if ( ETH_TX_DESC_CNT % 4 != 0 ) - #error "Invalid ETH_TX_DESC_CNT value for NetworkInterface, must be a multiple of 4" - #endif - - #if ( ETH_RX_DESC_CNT % 4 != 0 ) - #error "Invalid ETH_RX_DESC_CNT value for NetworkInterface, must be a multiple of 4" - #endif - -#endif - #if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) #if defined( niEMAC_STM32FX ) && defined( ETH_RX_BUF_SIZE ) @@ -229,40 +198,46 @@ #if defined( niEMAC_STM32FX ) - #ifdef ETH_GIANT_PACKET - #undef ETH_GIANT_PACKET - #endif - #define ETH_GIANT_PACKET ETH_DMARXDESC_IPV4HCE - - #ifdef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG - #undef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG - #endif + /* Note: ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ + #undef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG #define ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_RBUS - #ifdef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #endif + #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_TBUS /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ - #ifdef ETH_CTRLPACKETS_BLOCK_ALL - #undef ETH_CTRLPACKETS_BLOCK_ALL - #endif + #undef ETH_CTRLPACKETS_BLOCK_ALL #define ETH_CTRLPACKETS_BLOCK_ALL ETH_MACFFR_PCF_BlockAll + #undef ETH_IP_HEADER_IPV4 + #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR + + #undef ETH_IP_HEADER_IPV6 + #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR + + #undef ETH_IP_PAYLOAD_UNKNOWN + #define ETH_IP_PAYLOAD_UNKNOWN 0x0U + + #undef ETH_IP_PAYLOAD_UDP + #define ETH_IP_PAYLOAD_UDP ETH_DMAPTPRXDESC_IPPT_UDP + + #undef ETH_IP_PAYLOAD_TCP + #define ETH_IP_PAYLOAD_TCP ETH_DMAPTPRXDESC_IPPT_TCP + + #undef ETH_IP_PAYLOAD_ICMPN + #define ETH_IP_PAYLOAD_ICMPN ETH_DMAPTPRXDESC_IPPT_ICMP + #elif defined( niEMAC_STM32HX ) - #ifdef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #endif + #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMACSR_TBU - #define ETH_DMA_TX_ERRORS_MASK ETH_DMACSR_TEB - #define ETH_DMA_RX_ERRORS_MASK ETH_DMACSR_REB + #undef ETH_IP_PAYLOAD_IGMP + #define ETH_IP_PAYLOAD_IGMP 0x4U #endif -#define niEMAC_BUFS_PER_DESC 2U +#define ETH_IP_PAYLOAD_MASK 0x7U /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ #define niEMAC_CRC_POLY 0x04C11DB7 @@ -300,18 +275,7 @@ typedef enum eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; -/* typedef struct xPhyData -{ - EthernetPhy_t xPhyObject; - #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) - union { - lan8742_Object_t xLan8742a; - dp83848_Object_t xDp83848; - } xPhyInstance; - #endif -} PhyData_t; - -typedef struct xMacSrcMatchData +/* typedef struct xMacSrcMatchData { uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ]; uint8_t uxMACEntryIndex = 0; @@ -372,7 +336,7 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa #ifdef niEMAC_STM32HX static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); #endif -static BaseType_t prvPhyInit( ETH_TypeDef * const pxEthInstance, EthernetPhy_t * pxPhyObject ); +static BaseType_t prvPhyInit( EthernetPhy_t * pxPhyObject ); static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); /* MAC Filtering Helpers */ @@ -383,8 +347,8 @@ static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ); -static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex ); -static void prvRemoveDestMACAddrHash( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ); +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); /* EMAC Helpers */ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ); @@ -396,18 +360,6 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes /* Network Interface Definition */ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); -/* Reimplemented HAL Functions */ -static void prvHAL_ETH_SetHashTable( ETH_TypeDef * const pxEthInstance ); -static BaseType_t prvHAL_ETH_ReadPHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t * pulRegValue ); -static BaseType_t prvHAL_ETH_WritePHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t ulRegValue ); - -/* Debugging */ -#if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) - static void prvHAL_RX_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); - static void prvHAL_DMA_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); - static void prvHAL_MAC_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ); -#endif - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Static Variable Declarations */ @@ -420,11 +372,6 @@ static ETH_HandleTypeDef xEthHandle; static EthernetPhy_t xPhyObject; -#if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) - static lan8742_Object_t xLan8742aObject; - static dp83848_Object_t xDp83848Object; -#endif - static TaskHandle_t xEMACTaskHandle = NULL; static SemaphoreHandle_t xTxMutex = NULL, xTxDescSem = NULL; @@ -450,7 +397,7 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint { BaseType_t xResult = pdFALSE; - if( prvHAL_ETH_ReadPHYRegister( xEthHandle.Instance, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) != pdPASS ) + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) { xResult = pdTRUE; } @@ -464,7 +411,7 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uin { BaseType_t xResult = pdFALSE; - if( prvHAL_ETH_WritePHYRegister( xEthHandle.Instance, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) != pdPASS ) + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) { xResult = pdTRUE; } @@ -519,7 +466,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /* fallthrough */ case eMacPhyInit: - if( prvPhyInit( pxEthHandle->Instance, pxPhyObject ) == pdFALSE ) + if( prvPhyInit( pxPhyObject ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyInit failed\n" ) ); break; @@ -797,7 +744,7 @@ static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uin if( xResult == pdFALSE ) { - prvAddDestMACAddrHash( pxEthHandle->Instance, ucHashIndex ); + prvAddDestMACAddrHash( pxEthHandle, ucHashIndex ); } } } @@ -812,7 +759,7 @@ static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const if( xResult == pdFALSE ) { - prvRemoveDestMACAddrHash( pxEthHandle->Instance, pucMacAddress ); + prvRemoveDestMACAddrHash( pxEthHandle, pucMacAddress ); } } @@ -1037,9 +984,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte BaseType_t xResult = pdFALSE; pxEthHandle->Instance = ETH; - pxEthHandle->Init.MediaInterface = ipconfigIS_ENABLED( niEMAC_USE_RMII ) ? HAL_ETH_RMII_MODE : HAL_ETH_MII_MODE; - pxEthHandle->Init.RxBuffLen = niEMAC_DATA_BUFFER_SIZE; /* configASSERT( pxEthHandle->Init.RxBuffLen <= ETH_MAX_PACKET_SIZE ); */ configASSERT( pxEthHandle->Init.RxBuffLen % 4U == 0 ); @@ -1047,10 +992,6 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte configASSERT( pxEthHandle->Init.RxBuffLen == ETH_RX_BUF_SIZE ); #endif - #ifdef niEMAC_STM32HX - configASSERT( ETH_TX_DESC_CNT % 4 == 0 ); - configASSERT( ETH_RX_DESC_CNT % 4 == 0 ); - #endif static ETH_DMADescTypeDef xDMADescTx[ ETH_TX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_TX_DESC_SECTION ) ) ); static ETH_DMADescTypeDef xDMADescRx[ ETH_RX_DESC_CNT ] __ALIGNED( portBYTE_ALIGNMENT ) __attribute__( ( section( niEMAC_RX_DESC_SECTION ) ) ); pxEthHandle->Init.TxDesc = xDMADescTx; @@ -1064,13 +1005,12 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte /* ipLOCAL_MAC_ADDRESS */ pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; - #if defined( niEMAC_STM32FX ) - /* This function doesn't get called in Fxx driver */ - HAL_ETH_SetMDIOClockRange( pxEthHandle ); - #endif - if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) { + #if defined( niEMAC_STM32FX ) + /* This function doesn't get called in Fxx driver */ + HAL_ETH_SetMDIOClockRange( pxEthHandle ); + #endif ETH_MACConfigTypeDef xMACConfig; ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); @@ -1136,9 +1076,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte FreeRTOS_debug_printf( ( "prvEthConfigInit: ETH_IRQn was not enabled by application\n" ) ); HAL_NVIC_EnableIRQ( ETH_IRQn ); } - } - else - { + #ifdef niEMAC_STM32FX configASSERT( __HAL_RCC_ETH_IS_CLK_ENABLED() != 0 ); #elif defined( STM32H5 ) @@ -1223,13 +1161,12 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); } - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) ) + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) { ETH_L3FilterConfigTypeDef xL3FilterConfig; /* Filter out all possibilities if frame type is disabled */ - if( ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) ) - { + #if ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) /* Block IPv4 if it is disabled */ ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; @@ -1240,10 +1177,9 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - } + #endif - if( ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) && ( ucFilterCount > 1 ) ) - { + #if ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) /* Block IPv6 if it is disabled */ ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; @@ -1256,46 +1192,48 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - } + #endif - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + /* TODO: Handle multiple endpoints */ + #if 0 + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ) + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; - xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; + xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + #endif } - } - else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) - { - if( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) && ( ucFilterCount > 1 ) ) + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) { - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + #endif } } - } - } /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ + #endif /* if 0 */ + } + #endif /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ - if( ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) ) + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) { /* TODO: Let user to block certain port numbers */ /* TODO: Live updated in task based on active sockets? */ @@ -1322,6 +1260,7 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); } } + #endif HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); } @@ -1333,7 +1272,7 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI /*---------------------------------------------------------------------------*/ -static BaseType_t prvPhyInit( ETH_TypeDef * const pxEthInstance, EthernetPhy_t * pxPhyObject ) +static BaseType_t prvPhyInit( EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFAIL; @@ -1341,56 +1280,6 @@ static BaseType_t prvPhyInit( ETH_TypeDef * const pxEthInstance, EthernetPhy_t * if( xPhyDiscover( pxPhyObject ) != 0 ) { - #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) - for( size_t uxCount = 0; uxCount < pxPhyObject->xPortCount; ++uxCount ) - { - if( pxPhyObject->ulPhyIDs[ uxCount ] == PHY_ID_LAN8742A ) - { - xLan8742aObject.DevAddr = pxPhyObject->ucPhyIndexes[ uxCount ]; - lan8742_IOCtx_t xLan8742aControl = { - .Init = NULL, - .DeInit = NULL, - .WriteReg = ( lan8742_WriteReg_Func ) &prvPhyWriteReg, - .ReadReg = ( lan8742_ReadReg_Func ) &prvPhyReadReg, - #if ( INCLUDE_vTaskDelay == 1 ) - .GetTick = ( lan8742_GetTick_Func ) &vTaskDelay, - #else - .GetTick = ( lan8742_GetTick_Func ) &HAL_GetTick, - #endif - }; - ( void ) LAN8742_RegisterBusIO( &xLan8742aObject, &xLan8742aControl ); - xLan8742aObject.Is_Initialized = 1U; - if( LAN8742_EnableIT( &xLan8742aObject, LAN8742_LINK_DOWN_IT ) == LAN8742_STATUS_OK ) - { - pxEthInstance->MACIER |= ETH_MACIER_PHYIE; - } - break; - } - else if( pxPhyObject->ulPhyIDs[ uxCount ] == PHY_ID_DP83848I ) - { - xDp83848Object.DevAddr = pxPhyObject->ucPhyIndexes[ uxCount ]; - dp83848_IOCtx_t xDp83848Control = { - .Init = NULL, - .DeInit = NULL, - .WriteReg = ( dp83848_WriteReg_Func ) &prvPhyWriteReg, - .ReadReg = ( dp83848_ReadReg_Func ) &prvPhyReadReg, - #if ( INCLUDE_vTaskDelay == 1 ) - .GetTick = ( dp83848_GetTick_Func ) &vTaskDelay, - #else - .GetTick = ( dp83848_GetTick_Func ) &HAL_GetTick, - #endif - }; - ( void ) DP83848_RegisterBusIO( &xDp83848Object, &xDp83848Control ); - xDp83848Object.Is_Initialized = 1U; - if( DP83848_EnableIT( &xDp83848Object, DP83848_LINK_DOWN_IT ) == DP83848_STATUS_OK ) - { - pxEthInstance->MACIER |= ETH_MACIER_PHYIE; - } - break; - } - } - #endif /* if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) */ - xResult = pdPASS; } @@ -1608,7 +1497,7 @@ static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, /*---------------------------------------------------------------------------*/ -static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex ) +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ) { if( ucAddrHashCounters[ ucHashIndex ] == 0 ) { @@ -1621,7 +1510,7 @@ static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t uc ulHashTable[ 0 ] |= ( 1U << ucHashIndex ); } - prvHAL_ETH_SetHashTable( pxEthInstance ); + HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); } if( ucAddrHashCounters[ ucHashIndex ] < UINT8_MAX ) @@ -1632,7 +1521,7 @@ static void prvAddDestMACAddrHash( ETH_TypeDef * const pxEthInstance, uint8_t uc /*---------------------------------------------------------------------------*/ -static void prvRemoveDestMACAddrHash( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) { const uint8_t ucHashIndex = prvGetMacHashIndex( pucMACAddr ); @@ -1651,7 +1540,7 @@ static void prvRemoveDestMACAddrHash( ETH_TypeDef * const pxEthInstance, const u ulHashTable[ 0 ] &= ~( 1U << ucHashIndex ); } - prvHAL_ETH_SetHashTable( pxEthInstance ); + HAL_ETH_SetHashTable( pxEthHandle, ulHashTable ); } } } @@ -1709,13 +1598,6 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP xResult = pdTRUE; } - /* #if ipconfigIS_ENABLED( niEMAC_AUTO_LOW_POWER ) - if( ( pxEthHandle->Init.MediaInterface = HAL_ETH_MII_MODE ) && ( xMACConfig.DuplexMode == ETH_FULLDUPLEX_MODE ) && ( xMACConfig.Speed == ETH_SPEED_100M ) ) - { - HAL_ETHEx_EnterLPIMode( pxEthHandle, ENABLE, DISABLE ); - } - #endif */ - return xResult; } @@ -1778,9 +1660,6 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes ( void ) HAL_ETH_GetRxDataErrorCode( pxEthHandle, &ulErrorCode ); if( ulErrorCode != 0 ) { - #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) - prvHAL_RX_ErrorCallback( pxEthHandle ); - #endif iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_debug_printf( ( "prvAcceptPacket: Rx Data Error\n" ) ); break; @@ -1796,66 +1675,62 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes #endif #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + { + const ETH_DMADescTypeDef * const ulRxDesc = ( const ETH_DMADescTypeDef * const ) pxEthHandle->RxDescList.RxDesc[ pxEthHandle->RxDescList.RxDescIdx ]; + uint32_t ulRxDesc; #ifdef niEMAC_STM32HX - const ETH_DMADescTypeDef * const ulRxDesc = ( const ETH_DMADescTypeDef * const ) pxEthHandle->RxDescList.RxDesc[ pxEthHandle->RxDescList.RxDescIdx ]; - - const uint32_t ulRxDesc1 = ulRxDesc->DESC1; + ulRxDesc = ulRxDesc->DESC1; + #elif defined( niEMAC_STM32FX ) + ulRxDesc = ulRxDesc->DESC4; + #endif - if( ( ulRxDesc1 & ETH_CHECKSUM_IP_PAYLOAD_ERROR ) != 0 ) - { - iptraceETHERNET_RX_EVENT_LOST(); - break; - } + if( ( ulRxDesc & ETH_IP_HEADER_IPV4 ) != 0 ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + /* prvAllowIPPacketIPv4(); */ + #endif + } + else if( ( ulRxDesc & ETH_IP_HEADER_IPV6 ) != 0 ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + /* prvAllowIPPacketIPv6(); */ + #endif + } - if( ( ulRxDesc1 & ETH_CHECKSUM_IP_HEADER_ERROR ) != 0 ) - { + if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_UNKNOWN ) + { + iptraceETHERNET_RX_EVENT_LOST(); + break; + } + else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_UDP ) + { + /* prvProcessUDPPacket(); */ + } + else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_TCP ) + { + /* Should be impossible if hardware filtering is implemented correctly */ + configASSERT( ipconfigIS_ENABLED( ipconfigUSE_TCP ) ); + #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) + /* xProcessReceivedTCPPacket() */ + #endif + } + else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_ICMPN ) + { + #if ipconfigIS_DISABLED( ipconfigREPLY_TO_INCOMING_PINGS ) && ipconfigIS_DISABLED( ipconfigSUPPORT_OUTGOING_PINGS ) iptraceETHERNET_RX_EVENT_LOST(); break; - } - - if( ( ulRxDesc1 & ETH_IP_HEADER_IPV4 ) != 0 ) - { - /* Should be impossible if hardware filtering is implemented correctly */ - configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ); - #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) - /* prvAllowIPPacketIPv4(); */ - #endif - } - else if( ( ulRxDesc1 & ETH_IP_HEADER_IPV6 ) != 0 ) + #else + /* ProcessICMPPacket(); */ + #endif + } + #ifdef niEMAC_STM32HX + else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_IGMP ) /* IGMP */ { - /* Should be impossible if hardware filtering is implemented correctly */ - configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) ); - #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - /* prvAllowIPPacketIPv6(); */ - #endif - } - const uint32_t ulPacketType = ulRxDesc1 & ETH_DMARXNDESCWBF_PT; - if( ulPacketType == ETH_IP_PAYLOAD_UNKNOWN ) - { - iptraceETHERNET_RX_EVENT_LOST(); - break; - } - else if( ulPacketType == ETH_IP_PAYLOAD_UDP ) - { - /* prvProcessUDPPacket(); */ - } - else if( ulPacketType == ETH_IP_PAYLOAD_ICMPN ) - { - #if ipconfigIS_DISABLED( ipconfigREPLY_TO_INCOMING_PINGS ) && ipconfigIS_DISABLED( ipconfigSUPPORT_OUTGOING_PINGS ) - iptraceETHERNET_RX_EVENT_LOST(); - break; - #else - /* ProcessICMPPacket(); */ - #endif - } - else if( ulPacketType == ETH_IP_PAYLOAD_TCP ) - { - /* Should be impossible if hardware filtering is implemented correctly */ - configASSERT( ipconfigIS_ENABLED( ipconfigUSE_TCP ) ); - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) - /* xProcessReceivedTCPPacket() */ - #endif } #endif @@ -1866,6 +1741,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes FreeRTOS_debug_printf( ( "prvAcceptPacket: Packet discarded\n" ) ); break; } + } #endif xResult = pdTRUE; @@ -1890,26 +1766,6 @@ void ETH_IRQHandler( void ) xSwitchRequired = pdFALSE; HAL_ETH_IRQHandler( pxEthHandle ); - #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) - if( ( pxEthHandle->Instance->MACIER & ETH_MACIER_PHYIE ) != 0 ) - { - if( xLan8742aObject.Is_Initialized != 0 ) - { - if( LAN8742_GetITStatus( &xLan8742aObject, LAN8742_LINK_DOWN_IT ) ) - { - LAN8742_ClearIT( &xLan8742aObject, LAN8742_LINK_DOWN_IT ); - } - } - if( xDp83848Object.Is_Initialized != 0 ) - { - if( DP83848_GetITStatus( &xDp83848Object, DP83848_LINK_DOWN_IT ) ) - { - DP83848_ClearIT( &xDp83848Object, DP83848_LINK_DOWN_IT ); - } - } - } - #endif /* if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_USE_PHY_INT ) */ - portYIELD_FROM_ISR( xSwitchRequired ); } @@ -1929,9 +1785,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { eErrorEvents |= eMacEventErrDma; const uint32_t ulDmaError = pxEthHandle->DMAErrorCode; - #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) - prvHAL_DMA_ErrorCallback( pxEthHandle ); - #endif if( ( ulDmaError & ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) { eErrorEvents |= eMacEventErrTx; @@ -1946,9 +1799,6 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) if( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_MAC ) != 0 ) { eErrorEvents |= eMacEventErrMac; - #if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) - prvHAL_MAC_ErrorCallback( pxEthHandle ); - #endif } if( ( xEMACTaskHandle != NULL ) && ( eErrorEvents != eMacEventNone ) ) @@ -2005,27 +1855,6 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) } } -/*---------------------------------------------------------------------------*/ - -#ifdef niEMAC_STM32HX - -void HAL_ETH_EEECallback( ETH_HandleTypeDef * pxEthHandle ) -{ - switch( HAL_ETHEx_GetMACLPIEvent( pxEthHandle ) ) - { - case ETH_TX_LPI_ENTRY: - case ETH_TX_LPI_EXIT: - case ETH_RX_LPI_ENTRY: - case ETH_RX_LPI_EXIT: - break; - - default: - configASSERT( pdFALSE ); - } -} - -#endif - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* HAL Tx/Rx Callbacks */ @@ -2162,335 +1991,6 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net #endif -/*---------------------------------------------------------------------------*/ -/*===========================================================================*/ -/* Reimplemented HAL Functions */ -/*===========================================================================*/ -/*---------------------------------------------------------------------------*/ - -static void prvHAL_ETH_SetHashTable( ETH_TypeDef * const pxEthInstance ) -{ - #ifdef niEMAC_STM32FX - pxEthInstance->MACHTHR = ulHashTable[ 0 ]; - pxEthInstance->MACHTLR = ulHashTable[ 1 ]; - #elif defined( niEMAC_STM32HX ) - pxEthInstance->MACHT0R = ulHashTable[ 0 ]; - pxEthInstance->MACHT1R = ulHashTable[ 1 ]; - #endif -} - -/*---------------------------------------------------------------------------*/ - -static BaseType_t prvHAL_ETH_ReadPHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t * pulRegValue ) -{ - BaseType_t xResult = pdPASS; - - #ifdef niEMAC_STM32FX - uint32_t ulReg = pxEthInstance->MACMIIAR; - #elif defined( niEMAC_STM32HX ) - uint32_t ulReg = pxEthInstance->MACMDIOAR; - #endif - - #ifdef niEMAC_STM32FX - if( ( ulReg & ETH_MACMIIAR_MB ) != 0 ) - #elif defined( niEMAC_STM32HX ) - if( ( ulReg & ETH_MACMDIOAR_MB ) != 0 ) - #endif - { - xResult = pdFAIL; - } - else - { - #ifdef niEMAC_STM32FX - ulReg |= _VAL2FLD( ETH_MACMIIAR_PA, ulPhyAddr ); - ulReg |= _VAL2FLD( ETH_MACMIIAR_MR, ulPhyReg ); - ulReg &= ~ETH_MACMIIAR_MW; - ulReg |= ETH_MACMIIAR_MB; - pxEthInstance->MACMIIAR = ulReg; - #elif defined( niEMAC_STM32HX ) - ulReg |= _VAL2FLD( ETH_MACMDIOAR_PA, ulPhyAddr ); - ulReg |= _VAL2FLD( ETH_MACMDIOAR_RDA, ulPhyReg ); - MODIFY_REG( ulReg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD ); - ulReg |= ETH_MACMDIOAR_MB; - pxEthInstance->MACMDIOAR = ulReg; - #endif - - TimeOut_t xPhyWriteTimer; - vTaskSetTimeOutState( &xPhyWriteTimer ); - TickType_t xPhyWriteRemaining = pdMS_TO_TICKS( 0xFFFFU ); - #ifdef niEMAC_STM32FX - while( ( pxEthInstance->MACMIIAR & ETH_MACMIIAR_MB ) != 0 ) - #elif defined( niEMAC_STM32HX ) - while( ( pxEthInstance->MACMDIOAR & ETH_MACMDIOAR_MB ) != 0 ) - #endif - { - if( xTaskCheckForTimeOut( &xPhyWriteTimer, &xPhyWriteRemaining ) != pdFALSE ) - { - xResult = pdFAIL; - break; - } - else - { - vTaskDelay( pdMS_TO_TICKS( 1 ) ); - } - } - - #ifdef niEMAC_STM32FX - *pulRegValue = _FLD2VAL( ETH_MACMIIDR_MD, pxEthInstance->MACMIIDR ); - #elif defined( niEMAC_STM32HX ) - *pulRegValue = _FLD2VAL( ETH_MACMDIODR_MD, pxEthInstance->MACMDIODR ); - #endif - } - - return xResult; -} - -/*---------------------------------------------------------------------------*/ - -static BaseType_t prvHAL_ETH_WritePHYRegister( ETH_TypeDef * const pxEthInstance, uint32_t ulPhyAddr, uint32_t ulPhyReg, uint32_t ulRegValue ) -{ - BaseType_t xResult = pdPASS; - - #ifdef niEMAC_STM32FX - uint32_t ulReg = pxEthInstance->MACMIIAR; - #elif defined( niEMAC_STM32HX ) - uint32_t ulReg = pxEthInstance->MACMDIOAR; - #endif - - #ifdef niEMAC_STM32FX - if( ( ulReg & ETH_MACMIIAR_MB ) != 0 ) - #elif defined( niEMAC_STM32HX ) - if( ( ulReg & ETH_MACMDIOAR_MB ) != 0 ) - #endif - { - xResult = pdFAIL; - } - else - { - #ifdef niEMAC_STM32FX - ulReg |= _VAL2FLD( ETH_MACMIIAR_PA, ulPhyAddr ); - ulReg |= _VAL2FLD( ETH_MACMIIAR_MR, ulPhyReg ); - ulReg |= ETH_MACMIIAR_MW; - ulReg |= ETH_MACMIIAR_MB; - pxEthInstance->MACMIIDR = _VAL2FLD( ETH_MACMIIDR_MD, ( uint16_t ) ulRegValue ); - pxEthInstance->MACMIIAR = ulReg; - #elif defined( niEMAC_STM32HX ) - ulReg |= _VAL2FLD( ETH_MACMDIOAR_PA, ulPhyAddr ); - ulReg |= _VAL2FLD( ETH_MACMDIOAR_RDA, ulPhyReg ); - MODIFY_REG( ulReg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR ); - ulReg |= ETH_MACMDIOAR_MB; - pxEthInstance->MACMDIODR = _VAL2FLD( ETH_MACMDIODR_MD, ( uint16_t ) ulRegValue ); - pxEthInstance->MACMDIOAR = ulReg; - #endif - - TimeOut_t xPhyWriteTimer; - vTaskSetTimeOutState( &xPhyWriteTimer ); - TickType_t xPhyWriteRemaining = pdMS_TO_TICKS( 0xFFFFU ); - #ifdef niEMAC_STM32FX - while( ( pxEthInstance->MACMIIAR & ETH_MACMIIAR_MB ) != 0 ) - #elif defined( niEMAC_STM32HX ) - while( ( pxEthInstance->MACMDIOAR & ETH_MACMDIOAR_MB ) != 0 ) - #endif - { - if( xTaskCheckForTimeOut( &xPhyWriteTimer, &xPhyWriteRemaining ) != pdFALSE ) - { - xResult = pdFAIL; - break; - } - else - { - vTaskDelay( pdMS_TO_TICKS( 1 ) ); - } - } - } - - return xResult; -} - -/*---------------------------------------------------------------------------*/ -/*===========================================================================*/ -/* Debugging */ -/*===========================================================================*/ -/*---------------------------------------------------------------------------*/ - -#if ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) - -static void prvHAL_RX_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) -{ - uint32_t ulErrorCode = 0; - ( void ) HAL_ETH_GetRxDataErrorCode( pxEthHandle, &ulErrorCode ); - if( ( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) && ( ( ulErrorCode & ETH_DRIBBLE_BIT_ERROR ) != 0 ) ) - { - static size_t uxRxDBError = 0; - ++uxRxDBError; - } - if( ( ulErrorCode & ETH_RECEIVE_ERROR ) != 0 ) - { - static size_t uxRxRcvError = 0; - ++uxRxRcvError; - } - if( ( ulErrorCode & ETH_RECEIVE_OVERFLOW ) != 0 ) - { - static size_t uxRxROError = 0; - ++uxRxROError; - } - if( ( ulErrorCode & ETH_WATCHDOG_TIMEOUT ) != 0 ) - { - static size_t uxRxWDTError = 0; - ++uxRxWDTError; - } - if( ( ulErrorCode & ETH_GIANT_PACKET ) != 0 ) - { - static size_t uxRxGPError = 0; - ++uxRxGPError; - } - if( ( ulErrorCode & ETH_CRC_ERROR ) != 0 ) - { - static size_t uxRxCRCError = 0; - ++uxRxCRCError; - } -} - -/*---------------------------------------------------------------------------*/ - -static void prvHAL_DMA_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) -{ - #ifdef niEMAC_STM32HX - { - const uint32_t ulDmaError = pxEthHandle->DMAErrorCode; - if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) != ETH_DMA_RX_NO_ERROR_FLAG ) - { - /* if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_DESC_READ_ERROR_FLAG ) - { - static size_t uxDmaRDRError = 0; - ++uxDmaRDRError; - } - else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_DESC_WRITE_ERROR_FLAG ) - { - static size_t uxDmaRDWError = 0; - ++uxDmaRDWError; - } - else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_BUFFER_READ_ERROR_FLAG ) - { - static size_t uxDmaRBRError = 0; - ++uxDmaRBRError; - } - else if( ( ulDmaError & ETH_DMA_RX_ERRORS_MASK ) == ETH_DMA_RX_BUFFER_WRITE_ERROR_FLAG ) - { - static size_t uxDmaRBWError = 0; - ++uxDmaRBWError; - } */ - } - if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) != ETH_DMA_TX_NO_ERROR_FLAG ) - { - /* if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_DESC_READ_ERROR_FLAG ) - { - static size_t uxDmaTDRError = 0; - ++uxDmaTDRError; - } - else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_DESC_WRITE_ERROR_FLAG ) - { - static size_t uxDmaTDWError = 0; - ++uxDmaTDWError; - } - else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_BUFFER_READ_ERROR_FLAG ) - { - static size_t uxDmaTBRError = 0; - ++uxDmaTBRError; - } - else if( ( ulDmaError & ETH_DMA_TX_ERRORS_MASK ) == ETH_DMA_TX_BUFFER_WRITE_ERROR_FLAG ) - { - static size_t uxDmaTBWError = 0; - ++uxDmaTBWError; - } */ - } - if( ( ulDmaError & ETH_DMA_CONTEXT_DESC_ERROR_FLAG ) != 0 ) - { - static size_t uxDmaCDError = 0; - ++uxDmaCDError; - } - if( ( ulDmaError & ETH_DMA_FATAL_BUS_ERROR_FLAG ) != 0 ) - { - static size_t uxDmaFBEError = 0; - ++uxDmaFBEError; - } - if( ( ulDmaError & ETH_DMA_EARLY_TX_IT_FLAG ) != 0 ) - { - static size_t uxDmaETIError = 0; - ++uxDmaETIError; - } - if( ( ulDmaError & ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG ) != 0 ) - { - static size_t uxDmaRWTError = 0; - ++uxDmaRWTError; - } - if( ( ulDmaError & ETH_DMA_RX_PROCESS_STOPPED_FLAG ) != 0 ) - { - static size_t uxDmaRPSError = 0; - ++uxDmaRPSError; - } - if( ( ulDmaError & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) - { - static size_t uxDmaRBUError = 0; - ++uxDmaRBUError; - } - if( ( ulDmaError & ETH_DMA_TX_PROCESS_STOPPED_FLAG ) != 0 ) - { - static size_t uxDmaTPSError = 0; - ++uxDmaTPSError; - } - } - #endif /* ifdef niEMAC_STM32HX */ -} - -/*---------------------------------------------------------------------------*/ - -static void prvHAL_MAC_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) -{ - #ifdef niEMAC_STM32HX - { - const uint32_t ulMacError = pxEthHandle->MACErrorCode; - if( ( ulMacError & ETH_RECEIVE_WATCHDOG_TIMEOUT ) != 0 ) - { - static size_t uxMacRWTError = 0; - ++uxMacRWTError; - } - if( ( ulMacError & ETH_EXECESSIVE_COLLISIONS ) != 0 ) - { - static size_t uxMacECError = 0; - ++uxMacECError; - } - if( ( ulMacError & ETH_LATE_COLLISIONS ) != 0 ) - { - static size_t uxMacLCError = 0; - ++uxMacLCError; - } - if( ( ulMacError & ETH_EXECESSIVE_DEFERRAL ) != 0 ) - { - static size_t uxMacEDError = 0; - ++uxMacEDError; - } - if( ( ulMacError & ETH_LOSS_OF_CARRIER ) != 0 ) - { - static size_t uxMacLOCError = 0; - ++uxMacLOCError; - } - if( ( ulMacError & ETH_NO_CARRIER ) != 0 ) - { - static size_t uxMacNCError = 0; - ++uxMacNCError; - } - if( ( ulMacError & ETH_TRANSMIT_JABBR_TIMEOUT ) != 0 ) - { - static size_t uxMacTJTError = 0; - ++uxMacTJTError; - } - } - #endif /* ifdef niEMAC_STM32HX */ -} - -#endif /* ipconfigIS_ENABLED( niEMAC_DEBUG_ERROR ) */ - /*---------------------------------------------------------------------------*/ /*===========================================================================*/ /* Sample HAL User Functions */ From 9f1ccbcf2e717bdc0102d97b00a67471014e193b Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 30 Jan 2024 10:10:16 -0500 Subject: [PATCH 51/68] Fix function calls --- .../NetworkInterface/STM32/NetworkInterface.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 008224473f..9263a9af87 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1120,20 +1120,20 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) - prvAddAllowedMACAddress( xMDNS_MacAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xMDNS_MacAddress.ucBytes ); #endif #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) - prvAddAllowedMACAddress( xLLMNR_MacAddress.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xLLMNR_MacAddress.ucBytes ); #endif #endif #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - prvAddAllowedMACAddress( pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + prvAddAllowedMACAddress( pxInterface, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) - prvAddAllowedMACAddress( xMDNS_MACAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xMDNS_MACAddressIPv6.ucBytes ); #endif #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) - prvAddAllowedMACAddress( xLLMNR_MacAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xLLMNR_MacAddressIPv6.ucBytes ); #endif #endif } @@ -1248,8 +1248,7 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI xL4FilterConfig.DestinationPort = 0U; ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - if( ipconfigIS_DISABLED( ipconfigUSE_TCP ) ) - { + #if ipconfigIS_DISABLED( ipconfigUSE_TCP ) /* Block TCP if it is disabled */ ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; @@ -1258,7 +1257,7 @@ static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkI xL4FilterConfig.SourcePort = 0xFFFFU; xL4FilterConfig.DestinationPort = 0xFFFFU; ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - } + #endif } #endif From 4541b3e46bef26726a098e84517c0e26ee5c4fe3 Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 30 Jan 2024 10:24:57 -0500 Subject: [PATCH 52/68] fix cache enabled check --- .../NetworkInterface/STM32/NetworkInterface.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 9263a9af87..12aa4556c4 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -179,7 +179,7 @@ #define niEMAC_CACHEABLE ( defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) ) #if ( niEMAC_CACHEABLE != 0 ) #define niEMAC_CACHE_ENABLED ( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) - #define niEMAC_CACHE_MAINTENANCE ( niEMAC_CACHE_ENABLED && ipconfigIS_DISABLED( niEMAC_USE_MPU ) ) + #define niEMAC_CACHE_MAINTENANCE ( ipconfigIS_DISABLED( niEMAC_USE_MPU ) && niEMAC_CACHE_ENABLED ) #ifdef __SCB_DCACHE_LINE_SIZE #define niEMAC_DATA_ALIGNMENT __SCB_DCACHE_LINE_SIZE #else @@ -690,8 +690,8 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - #if defined( niEMAC_CACHEABLE ) - if( niEMAC_CACHE_MAINTENANCE ) + #if ( niEMAC_CACHEABLE != 0 ) + if( niEMAC_CACHE_MAINTENANCE != 0 ) { const uintptr_t uxDataStart = ( uintptr_t ) xTxBuffer.buffer; const uintptr_t uxLineStart = uxDataStart & ~niEMAC_DATA_ALIGNMENT_MASK; @@ -1865,8 +1865,8 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { - #ifdef niEMAC_CACHEABLE - if( niEMAC_CACHE_MAINTENANCE ) + #if ( niEMAC_CACHEABLE != 0 ) + if( niEMAC_CACHE_MAINTENANCE != 0 ) { SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pxBufferDescriptor->pucEthernetBuffer, pxBufferDescriptor->xDataLength ); } @@ -1905,8 +1905,8 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); - #ifdef niEMAC_CACHEABLE - if( niEMAC_CACHE_MAINTENANCE ) + #if ( niEMAC_CACHEABLE != 0 ) + if( niEMAC_CACHE_MAINTENANCE != 0 ) { SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pucBuff, usLength ); } From 05af7919858ff4eba2a7468d1412ea28d15a3e5e Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 30 Jan 2024 12:42:42 -0500 Subject: [PATCH 53/68] config checks --- .../NetworkInterface/STM32/NetworkInterface.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 12aa4556c4..0636cd77e0 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -123,6 +123,14 @@ #error "Task Notifications must be enabled for NetworkInterface" #endif +#if ipconfigIS_DISABLED( configUSE_COUNTING_SEMAPHORES ) + #error "Counting Semaphores must be enabled for NetworkInterface" +#endif + +#if ipconfigIS_DISABLED( configUSE_MUTEXES ) + #error "Mutexes must be enabled for NetworkInterface" +#endif + #if ipconfigIS_DISABLED( ipconfigZERO_COPY_TX_DRIVER ) #error "ipconfigZERO_COPY_TX_DRIVER must be enabled for NetworkInterface" #endif @@ -917,7 +925,9 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) xTxMutex = xSemaphoreCreateMutex(); #endif configASSERT( xTxMutex != NULL ); - vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + vQueueAddToRegistry( xTxMutex, niEMAC_TX_MUTEX_NAME ); + #endif } if( xTxDescSem == NULL ) @@ -936,7 +946,9 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) ); #endif configASSERT( xTxDescSem != NULL ); - vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); + #endif } if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) From 2c4cb01a7a43d46fe3eb6876c5b5571cab0936d5 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 1 Feb 2024 18:40:23 -0500 Subject: [PATCH 54/68] check static buffer size and fix caching defines --- .../NetworkInterface/STM32/NetworkInterface.c | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 0636cd77e0..d054902d5b 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -179,13 +179,13 @@ /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -#define niEMAC_MPU ( defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) ) -#if ( niEMAC_MPU != 0 ) +#if ( defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) ) + #define niEMAC_MPU #define niEMAC_MPU_ENABLED ( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ) #endif -#define niEMAC_CACHEABLE ( defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) ) -#if ( niEMAC_CACHEABLE != 0 ) +#if ( defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) ) + #define niEMAC_CACHEABLE #define niEMAC_CACHE_ENABLED ( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) #define niEMAC_CACHE_MAINTENANCE ( ipconfigIS_DISABLED( niEMAC_USE_MPU ) && niEMAC_CACHE_ENABLED ) #ifdef __SCB_DCACHE_LINE_SIZE @@ -194,7 +194,7 @@ #define niEMAC_DATA_ALIGNMENT 32U #endif #else - #define niEMAC_DATA_ALIGNMENT 4U + #define niEMAC_DATA_ALIGNMENT portBYTE_ALIGNMENT #endif #define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) @@ -698,7 +698,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - #if ( niEMAC_CACHEABLE != 0 ) + #ifdef niEMAC_CACHEABLE if( niEMAC_CACHE_MAINTENANCE != 0 ) { const uintptr_t uxDataStart = ( uintptr_t ) xTxBuffer.buffer; @@ -1060,11 +1060,11 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte if( xResult == pdTRUE ) { - #if defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) + #ifdef niEMAC_CACHEABLE if( niEMAC_CACHE_ENABLED ) { - #if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) - configASSERT( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ); + #ifdef niEMAC_MPU + configASSERT( niEMAC_MPU_ENABLED != 0 ); #else configASSERT( pdFALSE ); #endif @@ -1877,7 +1877,7 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); if( pxBufferDescriptor != NULL ) { - #if ( niEMAC_CACHEABLE != 0 ) + #ifdef niEMAC_CACHEABLE if( niEMAC_CACHE_MAINTENANCE != 0 ) { SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pxBufferDescriptor->pucEthernetBuffer, pxBufferDescriptor->xDataLength ); @@ -1917,7 +1917,7 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff *ppxEndDescriptor = pxCurDescriptor; /* Only single buffer packets are supported */ configASSERT( *ppxStartDescriptor == *ppxEndDescriptor ); - #if ( niEMAC_CACHEABLE != 0 ) + #ifdef niEMAC_CACHEABLE if( niEMAC_CACHE_MAINTENANCE != 0 ) { SCB_InvalidateDCache_by_Addr( ( uint32_t * ) pucBuff, usLength ); @@ -1950,6 +1950,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB { static uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ niEMAC_TOTAL_BUFFER_SIZE ] __ALIGNED( niEMAC_BUF_ALIGNMENT ) __attribute__( ( section( niEMAC_BUFFERS_SECTION ) ) ); + configASSERT( niEMAC_TOTAL_BUFFER_SIZE >= ipconfigETHERNET_MINIMUM_PACKET_BYTES ); configASSERT( xBufferAllocFixedSize == pdTRUE ); size_t uxIndex; From 1228bec3dde11aaa446e9ca9413c79b60cbec5f4 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Mon, 5 Feb 2024 16:36:26 +0000 Subject: [PATCH 55/68] Uncrustify: triggered by comment. --- .../NetworkInterface/STM32/NetworkInterface.c | 1175 +++++++++-------- 1 file changed, 640 insertions(+), 535 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index d054902d5b..1032c2718b 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -69,7 +69,7 @@ #error "This NetworkInterface is incompatible with STM32F2 - Use Legacy NetworkInterface" #else #error "Unknown STM32 Family for NetworkInterface" -#endif +#endif /* if defined( STM32F4 ) */ /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -83,31 +83,31 @@ #define niEMAC_STM32HX #endif -#define niEMAC_TASK_NAME "EMAC_STM32" -#define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) -#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) +#define niEMAC_TASK_NAME "EMAC_STM32" +#define niEMAC_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define niEMAC_TASK_STACK_SIZE ( 4U * configMINIMAL_STACK_SIZE ) -#define niEMAC_TX_DESC_SECTION ".TxDescripSection" -#define niEMAC_RX_DESC_SECTION ".RxDescripSection" -#define niEMAC_BUFFERS_SECTION ".EthBuffersSection" +#define niEMAC_TX_DESC_SECTION ".TxDescripSection" +#define niEMAC_RX_DESC_SECTION ".RxDescripSection" +#define niEMAC_BUFFERS_SECTION ".EthBuffersSection" -#define niEMAC_TASK_MAX_BLOCK_TIME_MS 100U -#define niEMAC_TX_MAX_BLOCK_TIME_MS 20U -#define niEMAC_RX_MAX_BLOCK_TIME_MS 20U -#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 20U +#define niEMAC_TASK_MAX_BLOCK_TIME_MS 100U +#define niEMAC_TX_MAX_BLOCK_TIME_MS 20U +#define niEMAC_RX_MAX_BLOCK_TIME_MS 20U +#define niEMAC_DESCRIPTOR_WAIT_TIME_MS 20U -#define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" -#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" +#define niEMAC_TX_MUTEX_NAME "EMAC_TxMutex" +#define niEMAC_TX_DESC_SEM_NAME "EMAC_TxDescSem" -#define niEMAC_AUTO_NEGOTIATION ipconfigENABLE -#define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) -#define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) +#define niEMAC_AUTO_NEGOTIATION ipconfigENABLE +#define niEMAC_USE_100MB ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_USE_FULL_DUPLEX ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_AUTO_CROSS ( ipconfigENABLE && ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ) +#define niEMAC_CROSSED_LINK ( ipconfigENABLE && ipconfigIS_DISABLED( niEMAC_AUTO_CROSS ) ) -#define niEMAC_USE_RMII ipconfigENABLE +#define niEMAC_USE_RMII ipconfigENABLE -#define niEMAC_USE_MPU ipconfigENABLE +#define niEMAC_USE_MPU ipconfigENABLE /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -161,17 +161,18 @@ #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES for NetworkInterface" #endif - /* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. - * So, don't use this macro, and filter anyways in the mean time. */ - /* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" - #endif */ +/* TODO: There should be a universal check for use in network interfaces, similar to eConsiderFrameForProcessing. + * So, don't use this macro, and filter anyways in the mean time. */ + +/* #if ipconfigIS_DISABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + #warning "Consider enabling ipconfigETHERNET_DRIVER_FILTERS_PACKETS for NetworkInterface" + #endif */ #if ipconfigIS_DISABLED( ipconfigUSE_LINKED_RX_MESSAGES ) #warning "Consider enabling ipconfigUSE_LINKED_RX_MESSAGES for NetworkInterface" #endif -#endif +#endif /* if ipconfigIS_DISABLED( ipconfigPORT_SUPPRESS_WARNING ) */ /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -181,78 +182,78 @@ #if ( defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) ) #define niEMAC_MPU - #define niEMAC_MPU_ENABLED ( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ) + #define niEMAC_MPU_ENABLED ( _FLD2VAL( MPU_CTRL_ENABLE, MPU->CTRL ) != 0 ) #endif #if ( defined( __DCACHE_PRESENT ) && ( __DCACHE_PRESENT == 1U ) ) #define niEMAC_CACHEABLE - #define niEMAC_CACHE_ENABLED ( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) - #define niEMAC_CACHE_MAINTENANCE ( ipconfigIS_DISABLED( niEMAC_USE_MPU ) && niEMAC_CACHE_ENABLED ) + #define niEMAC_CACHE_ENABLED ( _FLD2VAL( SCB_CCR_DC, SCB->CCR ) != 0 ) + #define niEMAC_CACHE_MAINTENANCE ( ipconfigIS_DISABLED( niEMAC_USE_MPU ) && niEMAC_CACHE_ENABLED ) #ifdef __SCB_DCACHE_LINE_SIZE #define niEMAC_DATA_ALIGNMENT __SCB_DCACHE_LINE_SIZE #else #define niEMAC_DATA_ALIGNMENT 32U #endif #else - #define niEMAC_DATA_ALIGNMENT portBYTE_ALIGNMENT + #define niEMAC_DATA_ALIGNMENT portBYTE_ALIGNMENT #endif -#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) -#define niEMAC_BUF_ALIGNMENT 32U -#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1U ) +#define niEMAC_DATA_ALIGNMENT_MASK ( niEMAC_DATA_ALIGNMENT - 1U ) +#define niEMAC_BUF_ALIGNMENT 32U +#define niEMAC_BUF_ALIGNMENT_MASK ( niEMAC_BUF_ALIGNMENT - 1U ) -#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) -#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) +#define niEMAC_DATA_BUFFER_SIZE ( ( ipTOTAL_ETHERNET_FRAME_SIZE + niEMAC_DATA_ALIGNMENT_MASK ) & ~niEMAC_DATA_ALIGNMENT_MASK ) +#define niEMAC_TOTAL_BUFFER_SIZE ( ( ( niEMAC_DATA_BUFFER_SIZE + ipBUFFER_PADDING ) + niEMAC_BUF_ALIGNMENT_MASK ) & ~niEMAC_BUF_ALIGNMENT_MASK ) #if defined( niEMAC_STM32FX ) - /* Note: ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ +/* Note: ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ #undef ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG - #define ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_RBUS + #define ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_RBUS #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_TBUS + #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMASR_TBUS - /* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ +/* Note: ETH_CTRLPACKETS_BLOCK_ALL is incorrectly defined in HAL ETH Driver as of F7 V1.17.1 && F4 V1.28.0 */ #undef ETH_CTRLPACKETS_BLOCK_ALL - #define ETH_CTRLPACKETS_BLOCK_ALL ETH_MACFFR_PCF_BlockAll + #define ETH_CTRLPACKETS_BLOCK_ALL ETH_MACFFR_PCF_BlockAll #undef ETH_IP_HEADER_IPV4 - #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR + #define ETH_IP_HEADER_IPV4 ETH_DMAPTPRXDESC_IPV4PR #undef ETH_IP_HEADER_IPV6 - #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR + #define ETH_IP_HEADER_IPV6 ETH_DMAPTPRXDESC_IPV6PR #undef ETH_IP_PAYLOAD_UNKNOWN - #define ETH_IP_PAYLOAD_UNKNOWN 0x0U + #define ETH_IP_PAYLOAD_UNKNOWN 0x0U #undef ETH_IP_PAYLOAD_UDP - #define ETH_IP_PAYLOAD_UDP ETH_DMAPTPRXDESC_IPPT_UDP + #define ETH_IP_PAYLOAD_UDP ETH_DMAPTPRXDESC_IPPT_UDP #undef ETH_IP_PAYLOAD_TCP - #define ETH_IP_PAYLOAD_TCP ETH_DMAPTPRXDESC_IPPT_TCP + #define ETH_IP_PAYLOAD_TCP ETH_DMAPTPRXDESC_IPPT_TCP #undef ETH_IP_PAYLOAD_ICMPN - #define ETH_IP_PAYLOAD_ICMPN ETH_DMAPTPRXDESC_IPPT_ICMP + #define ETH_IP_PAYLOAD_ICMPN ETH_DMAPTPRXDESC_IPPT_ICMP #elif defined( niEMAC_STM32HX ) #undef ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG - #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMACSR_TBU + #define ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ETH_DMACSR_TBU #undef ETH_IP_PAYLOAD_IGMP - #define ETH_IP_PAYLOAD_IGMP 0x4U + #define ETH_IP_PAYLOAD_IGMP 0x4U -#endif +#endif /* if defined( niEMAC_STM32FX ) */ -#define ETH_IP_PAYLOAD_MASK 0x7U +#define ETH_IP_PAYLOAD_MASK 0x7U /* IEEE 802.3 CRC32 polynomial - 0x04C11DB7 */ -#define niEMAC_CRC_POLY 0x04C11DB7 -#define niEMAC_MAC_IS_MULTICAST( MAC ) ( ( MAC[ 0 ] & 1U ) != 0 ) -#define niEMAC_MAC_IS_UNICAST( MAC ) ( ( MAC[ 0 ] & 1U ) == 0 ) -#define niEMAC_ADDRESS_HASH_BITS 64U -#define niEMAC_MAC_SRC_MATCH_COUNT 3U +#define niEMAC_CRC_POLY 0x04C11DB7 +#define niEMAC_MAC_IS_MULTICAST( MAC ) ( ( MAC[ 0 ] & 1U ) != 0 ) +#define niEMAC_MAC_IS_UNICAST( MAC ) ( ( MAC[ 0 ] & 1U ) == 0 ) +#define niEMAC_ADDRESS_HASH_BITS 64U +#define niEMAC_MAC_SRC_MATCH_COUNT 3U /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -261,7 +262,8 @@ /*---------------------------------------------------------------------------*/ /* Interrupt events to process: reception, transmission and error handling. */ -typedef enum { +typedef enum +{ eMacEventNone = 0, eMacEventRx = 1 << 0, eMacEventTx = 1 << 1, @@ -275,44 +277,44 @@ typedef enum { typedef enum { - eMacEthInit, /* Must initialise ETH. */ - eMacPhyInit, /* Must initialise PHY. */ - eMacPhyStart, /* Must start PHY. */ - eMacTaskStart, /* Must start deferred interrupt handler task. */ - eMacEthStart, /* Must start ETH. */ + eMacEthInit, /* Must initialise ETH. */ + eMacPhyInit, /* Must initialise PHY. */ + eMacPhyStart, /* Must start PHY. */ + eMacTaskStart, /* Must start deferred interrupt handler task. */ + eMacEthStart, /* Must start ETH. */ eMacInitComplete /* Initialisation was successful. */ } eMAC_INIT_STATUS_TYPE; /* typedef struct xMacSrcMatchData -{ - uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ]; - uint8_t uxMACEntryIndex = 0; -} MacSrcMatchData_t; - -typedef struct xMacHashData -{ - uint32_t ulHashTable[ niEMAC_ADDRESS_HASH_BITS / 32 ]; - uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ]; -} MacHashData_t; - -typedef struct xMacFilteringData -{ - MacSrcMatchData_t xSrcMatch; - MacHashData_t xHash; -} MacFilteringData_t; - -typedef struct xEMACData -{ - ETH_HandleTypeDef xEthHandle; - EthernetPhy_t xPhyObject; - TaskHandle_t xEMACTaskHandle; - SemaphoreHandle_t xTxMutex, xTxDescSem; - ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ]; - BaseType_t xSwitchRequired; - eMAC_INIT_STATUS_TYPE xMacInitStatus; - BaseType_t xEMACIndex; - MacFilteringData_t xMacFilteringData; -} EMACData_t; */ + * { + * uint8_t ucSrcMatchCounters[ niEMAC_MAC_SRC_MATCH_COUNT ]; + * uint8_t uxMACEntryIndex = 0; + * } MacSrcMatchData_t; + * + * typedef struct xMacHashData + * { + * uint32_t ulHashTable[ niEMAC_ADDRESS_HASH_BITS / 32 ]; + * uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ]; + * } MacHashData_t; + * + * typedef struct xMacFilteringData + * { + * MacSrcMatchData_t xSrcMatch; + * MacHashData_t xHash; + * } MacFilteringData_t; + * + * typedef struct xEMACData + * { + * ETH_HandleTypeDef xEthHandle; + * EthernetPhy_t xPhyObject; + * TaskHandle_t xEMACTaskHandle; + * SemaphoreHandle_t xTxMutex, xTxDescSem; + * ETH_BufferTypeDef xTxBuffers[ niEMAC_BUFS_PER_DESC * ETH_TX_DESC_CNT ]; + * BaseType_t xSwitchRequired; + * eMAC_INIT_STATUS_TYPE xMacInitStatus; + * BaseType_t xEMACIndex; + * MacFilteringData_t xMacFilteringData; + * } EMACData_t; */ /* TODO: need a data structure to assist in adding/removing allowed addresses */ @@ -323,50 +325,77 @@ typedef struct xEMACData /*---------------------------------------------------------------------------*/ /* Phy Hooks */ -static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ); -static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ); +static BaseType_t prvPhyReadReg( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t * pulValue ); +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t ulValue ); /* Network Interface Access Hooks */ static BaseType_t prvGetPhyLinkStatus( NetworkInterface_t * pxInterface ); static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterface ); -static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ); -static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ); -static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ); +static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t xReleaseAfterSend ); +static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, + const uint8_t * pucMacAddress ); +static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, + const uint8_t * pucMacAddress ); /* EMAC Task */ -static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -static __NO_RETURN portTASK_FUNCTION_PROTO( prvEMACHandlerTask, pvParameters ); +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ); +static __NO_RETURN portTASK_FUNCTION_PROTO( prvEMACHandlerTask, + pvParameters ); static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ); /* EMAC Init */ -static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ); +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ); +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ); #ifdef niEMAC_STM32HX - static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ); + static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, + const NetworkInterface_t * const pxInterface ); #endif static BaseType_t prvPhyInit( EthernetPhy_t * pxPhyObject ); -static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ); +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface, + EthernetPhy_t * pxPhyObject ); /* MAC Filtering Helpers */ static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ); static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ); -static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex, const uint8_t * const pucMACAddr ); -static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex ); -static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); -static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ); -static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ); -static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ); -static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucIndex, + const uint8_t * const pucMACAddr ); +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucIndex ); +static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + const uint8_t * const pucMACAddr ); +static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + const uint8_t * const pucMACAddr ); +static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucHashIndex, + const uint8_t * const pucMACAddr ); +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, + uint8_t ucHashIndex ); +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, + const uint8_t * const pucMACAddr ); /* EMAC Helpers */ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ); -static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ); +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, + EthernetPhy_t * pxPhyObject ); static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ); static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ); -static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ); +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, + uint16_t usLength ); /* Network Interface Definition */ -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ); +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ); /*---------------------------------------------------------------------------*/ /*===========================================================================*/ @@ -401,7 +430,9 @@ static uint8_t ucAddrHashCounters[ niEMAC_ADDRESS_HASH_BITS ] = { 0U }; /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) +static BaseType_t prvPhyReadReg( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t * pulValue ) { BaseType_t xResult = pdFALSE; @@ -415,7 +446,9 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint /*---------------------------------------------------------------------------*/ -static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) +static BaseType_t prvPhyWriteReg( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t ulValue ) { BaseType_t xResult = pdFALSE; @@ -464,6 +497,7 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac break; case eMacEthInit: + if( prvEthConfigInit( pxEthHandle, pxInterface ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacEthInit failed\n" ) ); @@ -471,9 +505,10 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac } xMacInitStatus = eMacPhyInit; - /* fallthrough */ + /* fallthrough */ case eMacPhyInit: + if( prvPhyInit( pxPhyObject ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyInit failed\n" ) ); @@ -481,9 +516,10 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac } xMacInitStatus = eMacPhyStart; - /* fallthrough */ + /* fallthrough */ case eMacPhyStart: + if( prvPhyStart( pxEthHandle, pxInterface, pxPhyObject ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacPhyStart failed\n" ) ); @@ -491,9 +527,10 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac } xMacInitStatus = eMacTaskStart; - /* fallthrough */ + /* fallthrough */ case eMacTaskStart: + if( prvEMACTaskStart( pxInterface ) == pdFALSE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacTaskStart failed\n" ) ); @@ -501,9 +538,10 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac } xMacInitStatus = eMacEthStart; - /* fallthrough */ + /* fallthrough */ case eMacEthStart: + if( pxEthHandle->gState != HAL_ETH_STATE_STARTED ) { if( HAL_ETH_Start_IT( pxEthHandle ) != HAL_OK ) @@ -514,9 +552,10 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac } xMacInitStatus = eMacInitComplete; - /* fallthrough */ + /* fallthrough */ case eMacInitComplete: + if( prvGetPhyLinkStatus( pxInterface ) != pdTRUE ) { FreeRTOS_debug_printf( ( "prvNetworkInterfaceInitialise: eMacInitComplete failed\n" ) ); @@ -531,9 +570,12 @@ static BaseType_t prvNetworkInterfaceInitialise( NetworkInterface_t * pxInterfac /*---------------------------------------------------------------------------*/ -static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, NetworkBufferDescriptor_t * const pxDescriptor, BaseType_t xReleaseAfterSend ) +static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, + NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t xReleaseAfterSend ) { BaseType_t xResult = pdFAIL; + /* Zero-Copy Only */ configASSERT( xReleaseAfterSend == pdTRUE ); @@ -570,7 +612,8 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N break; } - ETH_TxPacketConfig xTxConfig = { + ETH_TxPacketConfig xTxConfig = + { .CRCPadCtrl = ETH_CRC_PAD_INSERT, .Attributes = ETH_TX_PACKETS_FEATURES_CRCPAD, }; @@ -583,6 +626,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N #endif const EthernetHeader_t * const pxEthHeader = ( const EthernetHeader_t * const ) pxDescriptor->pucEthernetBuffer; + if( pxEthHeader->usFrameType == ipIPv4_FRAME_TYPE ) { #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) @@ -604,12 +648,13 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N { #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) TCPPacket_t * const pxTCPPacket = ( TCPPacket_t * const ) pxDescriptor->pucEthernetBuffer; + /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) - xTxConfig.MaxSegmentSize = ipconfigTCP_MSS; - xTxConfig.PayloadLen = pxDescriptor->xDataLength; - xTxConfig.TCPHeaderLen = ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ); - xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif */ + * xTxConfig.MaxSegmentSize = ipconfigTCP_MSS; + * xTxConfig.PayloadLen = pxDescriptor->xDataLength; + * xTxConfig.TCPHeaderLen = ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ); + * xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; + #endif */ ( void ) pxTCPPacket; #else FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); @@ -620,7 +665,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N UDPPacket_t * const pxUDPPacket = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; ( void ) pxUDPPacket; } - #else + #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv4\n" ) ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ } @@ -645,11 +690,12 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N { #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) TCPPacket_IPv6_t * const pxTCPPacket_IPv6 = ( TCPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; + /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) - xTxConfig.PayloadLen = pxDescriptor->xDataLength; - xTxConfig.TCPHeaderLen = sizeof( pxTCPPacket_IPv6->xTCPHeader ); - xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif */ + * xTxConfig.PayloadLen = pxDescriptor->xDataLength; + * xTxConfig.TCPHeaderLen = sizeof( pxTCPPacket_IPv6->xTCPHeader ); + * xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; + #endif */ ( void ) pxTCPPacket_IPv6; #else FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); @@ -660,19 +706,19 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N UDPPacket_t * const pxUDPPacket_IPv6 = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; ( void ) pxUDPPacket_IPv6; } - #else + #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv6\n" ) ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ } else if( pxEthHeader->usFrameType == ipARP_FRAME_TYPE ) { - } - ETH_BufferTypeDef xTxBuffer = { + ETH_BufferTypeDef xTxBuffer = + { .buffer = pxDescriptor->pucEthernetBuffer, - .len = pxDescriptor->xDataLength, - .next = NULL + .len = pxDescriptor->xDataLength, + .next = NULL }; xTxConfig.pData = pxDescriptor; @@ -680,10 +726,11 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N xTxConfig.Length = xTxBuffer.len; /* TODO: Queue Tx Output? */ + /* if( xQueueSendToBack( xTxQueue, pxDescriptor, 0 ) != pdPASS ) - { - xReleaseAfterSend = pdFALSE; - } */ + * { + * xReleaseAfterSend = pdFALSE; + * } */ if( xSemaphoreTake( xTxDescSem, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ) == pdFALSE ) { @@ -721,10 +768,9 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N configASSERT( pxEthHandle->gState == HAL_ETH_STATE_STARTED ); /* Should be impossible if semaphores are correctly implemented */ configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_BUSY ) == 0 ); - } - ( void ) xSemaphoreGive( xTxMutex ); + ( void ) xSemaphoreGive( xTxMutex ); } while( pdFALSE ); if( xReleaseAfterSend == pdTRUE ) @@ -737,7 +783,8 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, N /*---------------------------------------------------------------------------*/ -static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ) +static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, + const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; @@ -759,7 +806,8 @@ static void prvAddAllowedMACAddress( NetworkInterface_t * pxInterface, const uin /*---------------------------------------------------------------------------*/ -static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const uint8_t * pucMacAddress ) +static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, + const uint8_t * pucMacAddress ) { ETH_HandleTypeDef * pxEthHandle = &xEthHandle; @@ -777,25 +825,30 @@ static void prvRemoveAllowedMACAddress( NetworkInterface_t * pxInterface, const /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ) { BaseType_t xResult = pdFALSE; UBaseType_t uxCount = 0; + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) NetworkBufferDescriptor_t * pxStartDescriptor = NULL; NetworkBufferDescriptor_t * pxEndDescriptor = NULL; #endif NetworkBufferDescriptor_t * pxCurDescriptor = NULL; + if( ( xMacInitStatus == eMacInitComplete ) && ( pxEthHandle->gState == HAL_ETH_STATE_STARTED ) ) { while( HAL_ETH_ReadData( pxEthHandle, ( void ** ) &pxCurDescriptor ) == HAL_OK ) { ++uxCount; + if( pxCurDescriptor == NULL ) { /* Buffer was dropped, ignore packet */ continue; } + configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); pxCurDescriptor->pxInterface = pxInterface; @@ -809,10 +862,11 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, Net { pxEndDescriptor->pxNextBuffer = pxCurDescriptor; } + pxEndDescriptor = pxCurDescriptor; - #else + #else /* if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) */ prvSendRxEvent( pxCurDescriptor ); - #endif + #endif /* if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) */ } } @@ -837,7 +891,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) /* iptraceEMAC_TASK_STARTING(); */ - for( ;; ) + for( ; ; ) { BaseType_t xResult = pdFALSE; uint32_t ulISREvents = 0U; @@ -867,6 +921,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) if( ( ulISREvents & eMacEventErrEth ) != 0 ) { configASSERT( ( pxEthHandle->ErrorCode & HAL_ETH_ERROR_PARAM ) == 0 ); + if( pxEthHandle->gState == HAL_ETH_STATE_ERROR ) { /* Recover from critical error */ @@ -889,6 +944,7 @@ static portTASK_FUNCTION( prvEMACHandlerTask, pvParameters ) /* Recover from critical error */ ( void ) HAL_ETH_Init( pxEthHandle ); } + if( pxEthHandle->gState == HAL_ETH_STATE_READY ) { /* Link was down or critical error occurred */ @@ -938,20 +994,20 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT, &xTxDescSemBuf - ); + ); #else xTxDescSem = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TX_DESC_CNT, ( UBaseType_t ) ETH_TX_DESC_CNT - ); - #endif + ); + #endif /* if ( ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) ) */ configASSERT( xTxDescSem != NULL ); #if ( configQUEUE_REGISTRY_SIZE > 0 ) vQueueAddToRegistry( xTxDescSem, niEMAC_TX_DESC_SEM_NAME ); #endif } - if( xEMACTaskHandle == NULL && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) + if( ( xEMACTaskHandle == NULL ) && ( xTxMutex != NULL ) && ( xTxDescSem != NULL ) ) { #if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) static StackType_t uxEMACTaskStack[ niEMAC_TASK_STACK_SIZE ]; @@ -964,8 +1020,8 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) niEMAC_TASK_PRIORITY, uxEMACTaskStack, &xEMACTaskTCB - ); - #else + ); + #else /* if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) */ ( void ) xTaskCreate( prvEMACHandlerTask, niEMAC_TASK_NAME, @@ -973,8 +1029,8 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) ( void * ) pxInterface, niEMAC_TASK_PRIORITY, &xEMACTaskHandle - ); - #endif + ); + #endif /* if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) */ } if( xEMACTaskHandle != NULL ) @@ -991,7 +1047,8 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ) { BaseType_t xResult = pdFALSE; @@ -1012,6 +1069,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte ( void ) memset( &xDMADescRx, 0, sizeof( xDMADescRx ) ); const NetworkEndPoint_t * const pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); + if( pxEndPoint != NULL ) { /* ipLOCAL_MAC_ADDRESS */ @@ -1024,7 +1082,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte HAL_ETH_SetMDIOClockRange( pxEthHandle ); #endif ETH_MACConfigTypeDef xMACConfig; - ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + ( void ) HAL_ETH_GetMACConfig( pxEthHandle, &xMACConfig ); xMACConfig.ChecksumOffload = ( FunctionalState ) ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ); xMACConfig.CRCStripTypePacket = DISABLE; xMACConfig.AutomaticPadCRCStrip = ENABLE; @@ -1037,10 +1095,11 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte xDMAConfig.EnhancedDescriptorFormat = ( FunctionalState ) ( ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) || ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) ); #elif defined( niEMAC_STM32HX ) xDMAConfig.SecondPacketOperate = ENABLE; + /* #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) - xDMAConfig.TCPSegmentation = ENABLE; - xDMAConfig.MaximumSegmentSize = ipconfigTCP_MSS; - #endif */ + * xDMAConfig.TCPSegmentation = ENABLE; + * xDMAConfig.MaximumSegmentSize = ipconfigTCP_MSS; + #endif */ #endif ( void ) HAL_ETH_SetDMAConfig( pxEthHandle, &xDMAConfig ); @@ -1048,8 +1107,8 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte prvInitPacketFilter( pxEthHandle, pxInterface ); /* HAL_ETHEx_DisableARPOffload( pxEthHandle ); - HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulSourceIPAddress ); - HAL_ETHEx_EnableARPOffload( pxEthHandle ); */ + * HAL_ETHEx_SetARPAddressMatch( pxEthHandle, ulSourceIPAddress ); + * HAL_ETHEx_EnableARPOffload( pxEthHandle ); */ #endif prvInitMacAddresses( pxEthHandle, pxInterface ); @@ -1078,11 +1137,13 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte const uint32_t ulPrioBits = __NVIC_PRIO_BITS; #endif const uint32_t ulPriority = NVIC_GetPriority( ETH_IRQn ) << ( 8U - ulPrioBits ); + if( ulPriority < configMAX_SYSCALL_INTERRUPT_PRIORITY ) { FreeRTOS_debug_printf( ( "prvEthConfigInit: Incorrectly set ETH_IRQn priority\n" ) ); NVIC_SetPriority( ETH_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY >> ( 8U - ulPrioBits ) ); } + if( NVIC_GetEnableIRQ( ETH_IRQn ) == 0 ) { FreeRTOS_debug_printf( ( "prvEthConfigInit: ETH_IRQn was not enabled by application\n" ) ); @@ -1095,7 +1156,7 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte configASSERT( __HAL_RCC_ETH_IS_CLK_ENABLED() != 0 ); configASSERT( __HAL_RCC_ETHTX_IS_CLK_ENABLED() != 0 ); configASSERT( __HAL_RCC_ETHRX_IS_CLK_ENABLED() != 0 ); - #elif defined( STM32H7) + #elif defined( STM32H7 ) configASSERT( __HAL_RCC_ETH1MAC_IS_CLK_ENABLED() != 0 ); configASSERT( __HAL_RCC_ETH1TX_IS_CLK_ENABLED() != 0 ); configASSERT( __HAL_RCC_ETH1RX_IS_CLK_ENABLED() != 0 ); @@ -1107,9 +1168,11 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, NetworkInte /*---------------------------------------------------------------------------*/ -static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface ) +static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface ) { ETH_MACFilterConfigTypeDef xFilterConfig; + ( void ) HAL_ETH_GetMACFilterConfig( pxEthHandle, &xFilterConfig ); xFilterConfig.ReceiveAllMode = DISABLE; xFilterConfig.HachOrPerfectFilter = ENABLE; @@ -1125,6 +1188,7 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa ( void ) HAL_ETH_SetMACFilterConfig( pxEthHandle, &xFilterConfig ); NetworkEndPoint_t * pxEndPoint; + for( pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { prvAddAllowedMACAddress( pxInterface, pxEndPoint->xMACAddress.ucBytes ); @@ -1154,130 +1218,133 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, NetworkInterfa #ifdef niEMAC_STM32HX -static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, const NetworkInterface_t * const pxInterface ) -{ - HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); - - #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) + static void prvInitPacketFilter( ETH_HandleTypeDef * pxEthHandle, + const NetworkInterface_t * const pxInterface ) { - const uint8_t ucFilterCount = _FLD2VAL( ETH_MACHWF1R_L3L4FNUM, pxEthHandle->Instance->MACHWF1R ); - if( ucFilterCount > 0 ) + HAL_ETHEx_DisableL3L4Filtering( pxEthHandle ); + + #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) { - ETH_MACConfigTypeDef xMACConfig; - ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); - if( xMACConfig.ChecksumOffload != ENABLE ) - { - /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum - Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ - xMACConfig.ChecksumOffload = ENABLE; - ( void ) HAL_ETH_SetMACConfig( pxEthHandle , &xMACConfig ); - } + const uint8_t ucFilterCount = _FLD2VAL( ETH_MACHWF1R_L3L4FNUM, pxEthHandle->Instance->MACHWF1R ); - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + if( ucFilterCount > 0 ) { - ETH_L3FilterConfigTypeDef xL3FilterConfig; - - /* Filter out all possibilities if frame type is disabled */ - #if ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) - /* Block IPv4 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; - xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - #endif + ETH_MACConfigTypeDef xMACConfig; + ( void ) HAL_ETH_GetMACConfig( pxEthHandle, &xMACConfig ); - #if ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) - /* Block IPv6 if it is disabled */ - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - #endif + if( xMACConfig.ChecksumOffload != ENABLE ) + { + /* "The Layer 3 and Layer 4 Packet Filter feature automatically selects the IPC Full Checksum + * Offload Engine on the Receive side. When this feature is enabled, you must set the IPC bit." */ + xMACConfig.ChecksumOffload = ENABLE; + ( void ) HAL_ETH_SetMACConfig( pxEthHandle, &xMACConfig ); + } - /* TODO: Handle multiple endpoints */ - #if 0 - for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) - { - if( ENDPOINT_IS_IPv4( pxEndPoint ) ) - { - #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; - xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); - #endif - } - else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) + { + ETH_L3FilterConfigTypeDef xL3FilterConfig; + + /* Filter out all possibilities if frame type is disabled */ + #if ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) + /* Block IPv4 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = ipBROADCAST_IP_ADDRESS; + xL3FilterConfig.Ip4DestAddr = ipBROADCAST_IP_ADDRESS; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + #endif /* if ipconfigIS_DISABLED( ipconfigUSE_IPv4 ) */ + + #if ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) + /* Block IPv6 if it is disabled */ + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + #endif /* if ipconfigIS_DISABLED( ipconfigUSE_IPv6 ) */ + + /* TODO: Handle multiple endpoints */ + #if 0 + for( NetworkEndPoint_t * pxEndPoint = FreeRTOS_FirstEndPoint( pxInterface ); pxEndPoint != NULL; pxEndPoint = FreeRTOS_NextEndPoint( pxInterface, pxEndPoint ) ) { - #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; - xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; - xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; - xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ - xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; - xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; - xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; - ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); - #endif + if( ENDPOINT_IS_IPv4( pxEndPoint ) ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV4_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U /* Don't Care */; + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip4SrcAddr = 0U /* Don't Care */; + xL3FilterConfig.Ip4DestAddr = pxEndPoint->ipv4_settings.ulIPAddress; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_0, &xL3FilterConfig ); + #endif + } + else if( ENDPOINT_IS_IPv6( pxEndPoint ) ) + { + #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) + ( void ) HAL_ETHEx_GetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + xL3FilterConfig.Protocol = ETH_L3_IPV6_MATCH; + xL3FilterConfig.SrcAddrFilterMatch = ETH_L3_SRC_ADDR_MATCH_DISABLE; + xL3FilterConfig.DestAddrFilterMatch = ETH_L3_DEST_ADDR_MATCH_DISABLE; + xL3FilterConfig.SrcAddrHigherBitsMatch = 0U; /* Don't Care */ + xL3FilterConfig.DestAddrHigherBitsMatch = 0x1FU; + xL3FilterConfig.Ip6Addr[ 0 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 1 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 2 ] = 0xFFFFFFFFU; + xL3FilterConfig.Ip6Addr[ 3 ] = 0xFFFFFFFFU; + ( void ) HAL_ETHEx_SetL3FilterConfig( pxEthHandle, ETH_L3_FILTER_1, &xL3FilterConfig ); + #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ + } } - } - #endif /* if 0 */ - } - #endif /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ + #endif /* if 0 */ + } + #endif /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES ) */ - #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) - { - /* TODO: Let user to block certain port numbers */ - /* TODO: Live updated in task based on active sockets? */ - ETH_L4FilterConfigTypeDef xL4FilterConfig; - - /* Always allow all UDP */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; - xL4FilterConfig.SourcePort = 0U; - xL4FilterConfig.DestinationPort = 0U; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); - - #if ipconfigIS_DISABLED( ipconfigUSE_TCP ) - /* Block TCP if it is disabled */ - ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; - xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; - xL4FilterConfig.SourcePort = 0xFFFFU; - xL4FilterConfig.DestinationPort = 0xFFFFU; - ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); - #endif - } - #endif + #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) + { + /* TODO: Let user to block certain port numbers */ + /* TODO: Live updated in task based on active sockets? */ + ETH_L4FilterConfigTypeDef xL4FilterConfig; + + /* Always allow all UDP */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_UDP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_SRC_PORT_MATCH_DISABLE; + xL4FilterConfig.SourcePort = 0U; + xL4FilterConfig.DestinationPort = 0U; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_0, &xL4FilterConfig ); + + #if ipconfigIS_DISABLED( ipconfigUSE_TCP ) + /* Block TCP if it is disabled */ + ( void ) HAL_ETHEx_GetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + xL4FilterConfig.Protocol = ETH_L4_TCP_MATCH; + xL4FilterConfig.SrcPortFilterMatch = ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.DestPortFilterMatch = ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE; + xL4FilterConfig.SourcePort = 0xFFFFU; + xL4FilterConfig.DestinationPort = 0xFFFFU; + ( void ) HAL_ETHEx_SetL4FilterConfig( pxEthHandle, ETH_L4_FILTER_1, &xL4FilterConfig ); + #endif + } + #endif /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) */ - HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); + HAL_ETHEx_EnableL3L4Filtering( pxEthHandle ); + } } + #endif /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ } - #endif /* if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM ) */ -} #endif /* ifdef niEMAC_STM32HX */ @@ -1297,27 +1364,30 @@ static BaseType_t prvPhyInit( EthernetPhy_t * pxPhyObject ) return xResult; } -static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, NetworkInterface_t * pxInterface, EthernetPhy_t * pxPhyObject ) +static BaseType_t prvPhyStart( ETH_HandleTypeDef * pxEthHandle, + NetworkInterface_t * pxInterface, + EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { - const PhyProperties_t xPhyProperties = { + const PhyProperties_t xPhyProperties = + { #if ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) - .ucSpeed = PHY_SPEED_AUTO, + .ucSpeed = PHY_SPEED_AUTO, .ucDuplex = PHY_DUPLEX_AUTO, #else - .ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10, + .ucSpeed = ipconfigIS_ENABLED( niEMAC_USE_100MB ) ? PHY_SPEED_100 : PHY_SPEED_10, .ucDuplex = ipconfigIS_ENABLED( niEMAC_USE_FULL_DUPLEX ) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF, #endif #if ipconfigIS_ENABLED( niEMAC_AUTO_CROSS ) - .ucMDI_X = PHY_MDIX_AUTO, + .ucMDI_X = PHY_MDIX_AUTO, #elif ipconfigIS_ENABLED( niEMAC_CROSSED_LINK ) - .ucMDI_X = PHY_MDIX_CROSSED, + .ucMDI_X = PHY_MDIX_CROSSED, #else - .ucMDI_X = PHY_MDIX_DIRECT, + .ucMDI_X = PHY_MDIX_DIRECT, #endif }; @@ -1354,11 +1424,13 @@ static uint32_t prvCalcCrc32( const uint8_t * const pucMACAddr ) uint32_t ulCRC32 = 0xFFFFFFFFU; uint32_t ucIndex; + for( ucIndex = ipMAC_ADDRESS_LENGTH_BYTES; ucIndex > 0; --ucIndex ) { ulCRC32 ^= __RBIT( pucMACAddr[ ipMAC_ADDRESS_LENGTH_BYTES - ucIndex ] ); uint8_t ucJndex; + for( ucJndex = 8; ucJndex > 0; --ucJndex ) { if( ulCRC32 & 0x80000000U ) @@ -1389,7 +1461,9 @@ static uint8_t prvGetMacHashIndex( const uint8_t * const pucMACAddr ) /*---------------------------------------------------------------------------*/ /* Needed since HAL Driver only provides source matching */ -static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex, const uint8_t * const pucMACAddr ) +static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucIndex, + const uint8_t * const pucMACAddr ) { configASSERT( ucIndex < niEMAC_MAC_SRC_MATCH_COUNT ); const uint32_t ulMacAddrHigh = ( pucMACAddr[ 5 ] << 8 ) | ( pucMACAddr[ 4 ] ); @@ -1398,28 +1472,31 @@ static void prvHAL_ETH_SetDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, u /* MACA0HR/MACA0LR reserved for the primary MAC-address. */ const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); - ( * ( __IO uint32_t * ) ulMacRegHigh ) = ETH_MACA1HR_AE | ulMacAddrHigh; - ( * ( __IO uint32_t * ) ulMacRegLow ) = ulMacAddrLow; + ( *( __IO uint32_t * ) ulMacRegHigh ) = ETH_MACA1HR_AE | ulMacAddrHigh; + ( *( __IO uint32_t * ) ulMacRegLow ) = ulMacAddrLow; } /*---------------------------------------------------------------------------*/ -static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucIndex ) +static void prvHAL_ETH_ClearDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucIndex ) { configASSERT( ucIndex < niEMAC_MAC_SRC_MATCH_COUNT ); const uint32_t ulMacRegHigh = ( ( uint32_t ) &( pxEthInstance->MACA1HR ) + ( 8 * ucIndex ) ); const uint32_t ulMacRegLow = ( ( uint32_t ) &( pxEthInstance->MACA1LR ) + ( 8 * ucIndex ) ); - ( * ( __IO uint32_t * ) ulMacRegHigh ) = 0U; - ( * ( __IO uint32_t * ) ulMacRegLow ) = 0U; + ( *( __IO uint32_t * ) ulMacRegHigh ) = 0U; + ( *( __IO uint32_t * ) ulMacRegLow ) = 0U; } /*---------------------------------------------------------------------------*/ -static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) +static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; uint8_t ucIndex; + for( ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) { if( ucSrcMatchCounters[ ucIndex ] > 0U ) @@ -1437,6 +1514,7 @@ static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, con { ++( ucSrcMatchCounters[ ucIndex ] ); } + xResult = pdTRUE; break; } @@ -1452,11 +1530,13 @@ static BaseType_t prvAddDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, con /*---------------------------------------------------------------------------*/ -static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, const uint8_t * const pucMACAddr ) +static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; uint8_t ucIndex; + for( ucIndex = 0; ucIndex < niEMAC_MAC_SRC_MATCH_COUNT; ++ucIndex ) { if( ucSrcMatchCounters[ ucIndex ] > 0U ) @@ -1489,7 +1569,9 @@ static BaseType_t prvRemoveDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, /*---------------------------------------------------------------------------*/ -static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, uint8_t ucHashIndex, const uint8_t * const pucMACAddr ) +static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, + uint8_t ucHashIndex, + const uint8_t * const pucMACAddr ) { BaseType_t xResult = pdFALSE; @@ -1508,7 +1590,8 @@ static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, /*---------------------------------------------------------------------------*/ -static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHashIndex ) +static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, + uint8_t ucHashIndex ) { if( ucAddrHashCounters[ ucHashIndex ] == 0 ) { @@ -1532,7 +1615,8 @@ static void prvAddDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, uint8_t ucHa /*---------------------------------------------------------------------------*/ -static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, const uint8_t * const pucMACAddr ) +static void prvRemoveDestMACAddrHash( ETH_HandleTypeDef * pxEthHandle, + const uint8_t * const pucMACAddr ) { const uint8_t ucHashIndex = prvGetMacHashIndex( pucMACAddr ); @@ -1576,15 +1660,17 @@ static void prvReleaseTxPacket( ETH_HandleTypeDef * pxEthHandle ) } /* TODO: Is it possible for the semaphore and BuffersInUse to get out of sync? */ + /* while( ETH_TX_DESC_CNT - uxQueueMessagesWaiting( ( QueueHandle_t ) xTxDescSem ) > pxEthHandle->TxDescList.BuffersInUse ) - { - ( void ) xSemaphoreGive( xTxDescSem ); - } */ + * { + * ( void ) xSemaphoreGive( xTxDescSem ); + * } */ } /*---------------------------------------------------------------------------*/ -static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetPhy_t * pxPhyObject ) +static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, + EthernetPhy_t * pxPhyObject ) { BaseType_t xResult = pdFALSE; @@ -1594,7 +1680,7 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP } ETH_MACConfigTypeDef xMACConfig; - ( void ) HAL_ETH_GetMACConfig( pxEthHandle , &xMACConfig ); + ( void ) HAL_ETH_GetMACConfig( pxEthHandle, &xMACConfig ); #if ipconfigIS_ENABLED( niEMAC_AUTO_NEGOTIATION ) ( void ) xPhyStartAutoNegotiation( pxPhyObject, xPhyGetMask( pxPhyObject ) ); @@ -1617,6 +1703,7 @@ static BaseType_t prvMacUpdateConfig( ETH_HandleTypeDef * pxEthHandle, EthernetP static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const pxDescriptor ) { NetworkBufferDescriptor_t * pxDescriptorToClear = pxDescriptor; + while( pxDescriptorToClear != NULL ) { #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) @@ -1626,17 +1713,19 @@ static void prvReleaseNetworkBufferDescriptor( NetworkBufferDescriptor_t * const #endif vReleaseNetworkBufferAndDescriptor( pxDescriptorToClear ); pxDescriptorToClear = pxNext; - }; + } } /*---------------------------------------------------------------------------*/ static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) { - const IPStackEvent_t xRxEvent = { + const IPStackEvent_t xRxEvent = + { .eEventType = eNetworkRxEvent, - .pvData = ( void * ) pxDescriptor + .pvData = ( void * ) pxDescriptor }; + if( xSendEventStructToIPTask( &xRxEvent, pdMS_TO_TICKS( niEMAC_RX_MAX_BLOCK_TIME_MS ) ) != pdPASS ) { iptraceETHERNET_RX_EVENT_LOST(); @@ -1647,9 +1736,11 @@ static void prvSendRxEvent( NetworkBufferDescriptor_t * const pxDescriptor ) /*---------------------------------------------------------------------------*/ -static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, uint16_t usLength ) +static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDescriptor, + uint16_t usLength ) { BaseType_t xResult = pdFALSE; + do { if( pxDescriptor == NULL ) @@ -1669,6 +1760,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes ETH_HandleTypeDef * pxEthHandle = &xEthHandle; uint32_t ulErrorCode = 0; ( void ) HAL_ETH_GetRxDataErrorCode( pxEthHandle, &ulErrorCode ); + if( ulErrorCode != 0 ) { iptraceETHERNET_RX_EVENT_LOST(); @@ -1700,7 +1792,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes /* Should be impossible if hardware filtering is implemented correctly */ configASSERT( ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) ); #if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) - /* prvAllowIPPacketIPv4(); */ + /* prvAllowIPPacketIPv4(); */ #endif } else if( ( ulRxDesc & ETH_IP_HEADER_IPV6 ) != 0 ) @@ -1738,10 +1830,10 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes /* ProcessICMPPacket(); */ #endif } + #ifdef niEMAC_STM32HX else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_IGMP ) /* IGMP */ { - } #endif @@ -1753,10 +1845,9 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes break; } } - #endif + #endif /* if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) */ xResult = pdTRUE; - } while( pdFALSE ); return xResult; @@ -1796,6 +1887,7 @@ void HAL_ETH_ErrorCallback( ETH_HandleTypeDef * pxEthHandle ) { eErrorEvents |= eMacEventErrDma; const uint32_t ulDmaError = pxEthHandle->DMAErrorCode; + if( ( ulDmaError & ETH_DMA_TX_BUFFER_UNAVAILABLE_FLAG ) != 0 ) { eErrorEvents |= eMacEventErrTx; @@ -1875,6 +1967,7 @@ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * pxEthHandle ) void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) { const NetworkBufferDescriptor_t * pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( niEMAC_DATA_BUFFER_SIZE, pdMS_TO_TICKS( niEMAC_DESCRIPTOR_WAIT_TIME_MS ) ); + if( pxBufferDescriptor != NULL ) { #ifdef niEMAC_CACHEABLE @@ -1893,21 +1986,27 @@ void HAL_ETH_RxAllocateCallback( uint8_t ** ppucBuff ) /*---------------------------------------------------------------------------*/ -void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff, uint16_t usLength ) +void HAL_ETH_RxLinkCallback( void ** ppvStart, + void ** ppvEnd, + uint8_t * pucBuff, + uint16_t usLength ) { NetworkBufferDescriptor_t ** const ppxStartDescriptor = ( NetworkBufferDescriptor_t ** ) ppvStart; NetworkBufferDescriptor_t ** const ppxEndDescriptor = ( NetworkBufferDescriptor_t ** ) ppvEnd; NetworkBufferDescriptor_t * const pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( ( const void * ) pucBuff ); + if( prvAcceptPacket( pxCurDescriptor, usLength ) == pdTRUE ) { pxCurDescriptor->xDataLength = usLength; #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) pxCurDescriptor->pxNextBuffer = NULL; #endif + if( *ppxStartDescriptor == NULL ) { *ppxStartDescriptor = pxCurDescriptor; } + #if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) else if( ppxEndDescriptor != NULL ) { @@ -1936,6 +2035,7 @@ void HAL_ETH_RxLinkCallback( void ** ppvStart, void ** ppvEnd, uint8_t * pucBuff void HAL_ETH_TxFreeCallback( uint32_t * pulBuff ) { NetworkBufferDescriptor_t * const pxNetworkBuffer = ( NetworkBufferDescriptor_t * ) pulBuff; + prvReleaseNetworkBufferDescriptor( pxNetworkBuffer ); ( void ) xSemaphoreGive( xTxDescSem ); } @@ -1954,6 +2054,7 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB configASSERT( xBufferAllocFixedSize == pdTRUE ); size_t uxIndex; + for( uxIndex = 0; uxIndex < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ++uxIndex ) { pxNetworkBuffers[ uxIndex ].pucEthernetBuffer = &( ucNetworkPackets[ uxIndex ][ ipBUFFER_PADDING ] ); @@ -1967,7 +2068,8 @@ void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkB /*===========================================================================*/ /*---------------------------------------------------------------------------*/ -NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) +NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) { static char pcName[ 17 ]; @@ -1983,8 +2085,9 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net pxInterface->pfInitialise = prvNetworkInterfaceInitialise; pxInterface->pfOutput = prvNetworkInterfaceOutput; pxInterface->pfGetPhyLinkStatus = prvGetPhyLinkStatus; + /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; - pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ + * pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ return FreeRTOS_AddNetworkInterface( pxInterface ); } @@ -1996,7 +2099,8 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net /* Do not call the following function directly. It is there for downward compatibility. * The function FreeRTOS_IPInit() will call it to initialice the interface and end-point * objects. See the description in FreeRTOS_Routing.h. */ - NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, NetworkInterface_t * pxInterface ) + NetworkInterface_t * pxFillInterfaceDescriptor( BaseType_t xEMACIndex, + NetworkInterface_t * pxInterface ) { pxSTM32_FillInterfaceDescriptor( xEMACIndex, pxInterface ); } @@ -2012,266 +2116,267 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, Net #if 0 /** - * @brief Initializes the ETH MSP. - * @param heth: ETH handle - * @retval None -*/ -void HAL_ETH_MspInit( ETH_HandleTypeDef * pxEthHandle ) -{ - if( pxEthHandle->Instance == ETH ) + * @brief Initializes the ETH MSP. + * @param heth: ETH handle + * @retval None + */ + void HAL_ETH_MspInit( ETH_HandleTypeDef * pxEthHandle ) { - /* Enable ETHERNET clock */ - #ifdef niEMAC_STM32FX - __HAL_RCC_ETH_CLK_ENABLE(); - #elif defined( STM32H5 ) - __HAL_RCC_ETH_CLK_ENABLE(); - __HAL_RCC_ETHTX_CLK_ENABLE(); - __HAL_RCC_ETHRX_CLK_ENABLE(); - #elif defined( STM32H7) - __HAL_RCC_ETH1MAC_CLK_ENABLE(); - __HAL_RCC_ETH1TX_CLK_ENABLE(); - __HAL_RCC_ETH1RX_CLK_ENABLE(); - #endif - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOD_CLK_ENABLE(); - __HAL_RCC_GPIOE_CLK_ENABLE(); - __HAL_RCC_GPIOF_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - __HAL_RCC_GPIOH_CLK_ENABLE(); - - /* Ethernet pins configuration ************************************************/ - /* - Common Pins - ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin - ETH_MDIO ---------------------> - ETH_RXD0 ---------------------> - ETH_RXD1 ---------------------> - ETH_TX_EN --------------------> - ETH_TXD0 ---------------------> - ETH_TXD1 ---------------------> - - RMII Specific Pins - ETH_REF_CLK ------------------> - ETH_CRS_DV -------------------> - - MII Specific Pins - ETH_RX_CLK -------------------> - ETH_RX_ER --------------------> - ETH_RX_DV --------------------> - ETH_RXD2 ---------------------> - ETH_RXD3 ---------------------> - ETH_TX_CLK -------------------> - ETH_TXD2 ---------------------> - ETH_TXD3 ---------------------> - ETH_CRS ----------------------> - ETH_COL ----------------------> - */ - - GPIO_InitTypeDef GPIO_InitStructure = { 0 }; - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - - GPIO_InitStructure.Pin = ETH_MDC_Pin; - GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; - HAL_GPIO_Init( ETH_MDC_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - - GPIO_InitStructure.Pin = ETH_MDIO_Pin; - HAL_GPIO_Init( ETH_MDIO_Port, &GPIO_InitStructure ); - - GPIO_InitStructure.Pin = ETH_RXD0_Pin; - HAL_GPIO_Init( ETH_RXD0_Port, &GPIO_InitStructure ); - - GPIO_InitStructure.Pin = ETH_RXD1_Pin; - HAL_GPIO_Init( ETH_RXD1_Port, &GPIO_InitStructure ); - - GPIO_InitStructure.Pin = ETH_TX_EN_Pin; - HAL_GPIO_Init( ETH_TX_EN_Port, &GPIO_InitStructure ); - - GPIO_InitStructure.Pin = ETH_TXD0_Pin; - HAL_GPIO_Init( ETH_TXD0_Port, &GPIO_InitStructure ); - - GPIO_InitStructure.Pin = ETH_TXD1_Pin; - HAL_GPIO_Init( ETH_TXD1_Port, &GPIO_InitStructure ); - - if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) + if( pxEthHandle->Instance == ETH ) { - GPIO_InitStructure.Pin = ETH_REF_CLK_Pin; - HAL_GPIO_Init( ETH_REF_CLK_Port, &GPIO_InitStructure ); + /* Enable ETHERNET clock */ + #ifdef niEMAC_STM32FX + __HAL_RCC_ETH_CLK_ENABLE(); + #elif defined( STM32H5 ) + __HAL_RCC_ETH_CLK_ENABLE(); + __HAL_RCC_ETHTX_CLK_ENABLE(); + __HAL_RCC_ETHRX_CLK_ENABLE(); + #elif defined( STM32H7 ) + __HAL_RCC_ETH1MAC_CLK_ENABLE(); + __HAL_RCC_ETH1TX_CLK_ENABLE(); + __HAL_RCC_ETH1RX_CLK_ENABLE(); + #endif - GPIO_InitStructure.Pin = ETH_CRS_DV_Pin; - HAL_GPIO_Init( ETH_CRS_DV_Port, &GPIO_InitStructure ); - } - else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) - { - GPIO_InitStructure.Pin = ETH_RX_CLK_Pin; - HAL_GPIO_Init( ETH_RX_CLK_Port, &GPIO_InitStructure ); + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + + /* Ethernet pins configuration ************************************************/ + + /* + * Common Pins + * ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin + * ETH_MDIO ---------------------> + * ETH_RXD0 ---------------------> + * ETH_RXD1 ---------------------> + * ETH_TX_EN --------------------> + * ETH_TXD0 ---------------------> + * ETH_TXD1 ---------------------> + * + * RMII Specific Pins + * ETH_REF_CLK ------------------> + * ETH_CRS_DV -------------------> + * + * MII Specific Pins + * ETH_RX_CLK -------------------> + * ETH_RX_ER --------------------> + * ETH_RX_DV --------------------> + * ETH_RXD2 ---------------------> + * ETH_RXD3 ---------------------> + * ETH_TX_CLK -------------------> + * ETH_TXD2 ---------------------> + * ETH_TXD3 ---------------------> + * ETH_CRS ----------------------> + * ETH_COL ----------------------> + */ + + GPIO_InitTypeDef GPIO_InitStructure = { 0 }; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + + GPIO_InitStructure.Pin = ETH_MDC_Pin; + GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM; + HAL_GPIO_Init( ETH_MDC_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + + GPIO_InitStructure.Pin = ETH_MDIO_Pin; + HAL_GPIO_Init( ETH_MDIO_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_RXD0_Pin; + HAL_GPIO_Init( ETH_RXD0_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_RXD1_Pin; + HAL_GPIO_Init( ETH_RXD1_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_TX_EN_Pin; + HAL_GPIO_Init( ETH_TX_EN_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_TXD0_Pin; + HAL_GPIO_Init( ETH_TXD0_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_TXD1_Pin; + HAL_GPIO_Init( ETH_TXD1_Port, &GPIO_InitStructure ); + + if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) + { + GPIO_InitStructure.Pin = ETH_REF_CLK_Pin; + HAL_GPIO_Init( ETH_REF_CLK_Port, &GPIO_InitStructure ); + + GPIO_InitStructure.Pin = ETH_CRS_DV_Pin; + HAL_GPIO_Init( ETH_CRS_DV_Port, &GPIO_InitStructure ); + } + else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) + { + GPIO_InitStructure.Pin = ETH_RX_CLK_Pin; + HAL_GPIO_Init( ETH_RX_CLK_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_RX_ER_Pin; - HAL_GPIO_Init( ETH_RX_ER_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_RX_ER_Pin; + HAL_GPIO_Init( ETH_RX_ER_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_RX_DV_Pin; - HAL_GPIO_Init( ETH_RX_DV_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_RX_DV_Pin; + HAL_GPIO_Init( ETH_RX_DV_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_RXD2_Pin; - HAL_GPIO_Init( ETH_RXD2_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_RXD2_Pin; + HAL_GPIO_Init( ETH_RXD2_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_RXD3_Pin; - HAL_GPIO_Init( ETH_RXD3_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_RXD3_Pin; + HAL_GPIO_Init( ETH_RXD3_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_TX_CLK_Pin; - HAL_GPIO_Init( ETH_TX_CLK_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_TX_CLK_Pin; + HAL_GPIO_Init( ETH_TX_CLK_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_TXD2_Pin; - HAL_GPIO_Init( ETH_TXD2_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_TXD2_Pin; + HAL_GPIO_Init( ETH_TXD2_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_TXD3_Pin; - HAL_GPIO_Init( ETH_TXD3_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_TXD3_Pin; + HAL_GPIO_Init( ETH_TXD3_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_COL_Pin; - HAL_GPIO_Init( ETH_COL_Port, &GPIO_InitStructure ); + GPIO_InitStructure.Pin = ETH_COL_Pin; + HAL_GPIO_Init( ETH_COL_Port, &GPIO_InitStructure ); - GPIO_InitStructure.Pin = ETH_CRS_Pin; - HAL_GPIO_Init( ETH_CRS_Port, &GPIO_InitStructure ); - } + GPIO_InitStructure.Pin = ETH_CRS_Pin; + HAL_GPIO_Init( ETH_CRS_Port, &GPIO_InitStructure ); + } - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY, 0 ); - HAL_NVIC_EnableIRQ( ETH_IRQn ); + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority( ETH_IRQn, ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY, 0 ); + HAL_NVIC_EnableIRQ( ETH_IRQn ); + } } -} /*---------------------------------------------------------------------------*/ -void HAL_ETH_MspDeInit( ETH_HandleTypeDef * pxEthHandle ) -{ - if( pxEthHandle->Instance == ETH ) + void HAL_ETH_MspDeInit( ETH_HandleTypeDef * pxEthHandle ) { - /* Peripheral clock disable */ - #ifdef niEMAC_STM32FX - __HAL_RCC_ETH_CLK_DISABLE(); - #elif defined( STM32H5 ) - __HAL_RCC_ETH_CLK_DISABLE(); - __HAL_RCC_ETHTX_CLK_DISABLE(); - __HAL_RCC_ETHRX_CLK_DISABLE(); - #elif defined( STM32H7) - __HAL_RCC_ETH1MAC_CLK_DISABLE(); - __HAL_RCC_ETH1TX_CLK_DISABLE(); - __HAL_RCC_ETH1RX_CLK_DISABLE(); - #endif - - /**ETH GPIO Configuration - Common Pins - ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin - ETH_MDIO ---------------------> - ETH_RXD0 ---------------------> - ETH_RXD1 ---------------------> - ETH_TX_EN --------------------> - ETH_TXD0 ---------------------> - ETH_TXD1 ---------------------> - - RMII Specific Pins - ETH_REF_CLK ------------------> - ETH_CRS_DV -------------------> - - MII Specific Pins - ETH_RX_CLK -------------------> - ETH_RX_ER --------------------> - ETH_RX_DV --------------------> - ETH_RXD2 ---------------------> - ETH_RXD3 ---------------------> - ETH_TX_CLK -------------------> - ETH_TXD2 ---------------------> - ETH_TXD3 ---------------------> - ETH_CRS ----------------------> - ETH_COL ----------------------> - */ - - HAL_GPIO_DeInit( ETH_MDC_Port, ETH_MDC_Pin ); - HAL_GPIO_DeInit( ETH_MDIO_Port, ETH_MDIO_Pin ); - HAL_GPIO_DeInit( ETH_RXD0_Port, ETH_RXD0_Pin ); - HAL_GPIO_DeInit( ETH_RXD1_Port, ETH_RXD1_Pin ); - HAL_GPIO_DeInit( ETH_TX_EN_Port, ETH_TX_EN_Pin ); - HAL_GPIO_DeInit( ETH_TXD0_Port, ETH_TXD0_Pin ); - HAL_GPIO_DeInit( ETH_TXD1_Port, ETH_TXD1_Pin ); - - if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) - { - HAL_GPIO_DeInit( ETH_REF_CLK_Port, ETH_REF_CLK_Pin ); - HAL_GPIO_DeInit( ETH_CRS_DV_Port, ETH_CRS_DV_Pin ); - } - else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) + if( pxEthHandle->Instance == ETH ) { - HAL_GPIO_DeInit( ETH_RX_CLK_Port, ETH_RX_CLK_Pin ); - HAL_GPIO_DeInit( ETH_RX_ER_Port, ETH_RX_ER_Pin ); - HAL_GPIO_DeInit( ETH_RX_DV_Port, ETH_RX_DV_Pin ); - HAL_GPIO_DeInit( ETH_RXD2_Port, ETH_RXD2_Pin ); - HAL_GPIO_DeInit( ETH_RXD3_Port, ETH_RXD3_Pin ); - HAL_GPIO_DeInit( ETH_TX_CLK_Port, ETH_TX_CLK_Pin ); - HAL_GPIO_DeInit( ETH_TXD2_Port, ETH_TXD2_Pin ); - HAL_GPIO_DeInit( ETH_TXD3_Port, ETH_TXD3_Pin ); - HAL_GPIO_DeInit( ETH_COL_Port, ETH_COL_Pin ); - HAL_GPIO_DeInit( ETH_CRS_Port, ETH_CRS_Pin ); - } + /* Peripheral clock disable */ + #ifdef niEMAC_STM32FX + __HAL_RCC_ETH_CLK_DISABLE(); + #elif defined( STM32H5 ) + __HAL_RCC_ETH_CLK_DISABLE(); + __HAL_RCC_ETHTX_CLK_DISABLE(); + __HAL_RCC_ETHRX_CLK_DISABLE(); + #elif defined( STM32H7 ) + __HAL_RCC_ETH1MAC_CLK_DISABLE(); + __HAL_RCC_ETH1TX_CLK_DISABLE(); + __HAL_RCC_ETH1RX_CLK_DISABLE(); + #endif + + /**ETH GPIO Configuration + * Common Pins + * ETH_MDC ----------------------> ETH_MDC_Port, ETH_MDC_Pin + * ETH_MDIO ---------------------> + * ETH_RXD0 ---------------------> + * ETH_RXD1 ---------------------> + * ETH_TX_EN --------------------> + * ETH_TXD0 ---------------------> + * ETH_TXD1 ---------------------> + * + * RMII Specific Pins + * ETH_REF_CLK ------------------> + * ETH_CRS_DV -------------------> + * + * MII Specific Pins + * ETH_RX_CLK -------------------> + * ETH_RX_ER --------------------> + * ETH_RX_DV --------------------> + * ETH_RXD2 ---------------------> + * ETH_RXD3 ---------------------> + * ETH_TX_CLK -------------------> + * ETH_TXD2 ---------------------> + * ETH_TXD3 ---------------------> + * ETH_CRS ----------------------> + * ETH_COL ----------------------> + */ + + HAL_GPIO_DeInit( ETH_MDC_Port, ETH_MDC_Pin ); + HAL_GPIO_DeInit( ETH_MDIO_Port, ETH_MDIO_Pin ); + HAL_GPIO_DeInit( ETH_RXD0_Port, ETH_RXD0_Pin ); + HAL_GPIO_DeInit( ETH_RXD1_Port, ETH_RXD1_Pin ); + HAL_GPIO_DeInit( ETH_TX_EN_Port, ETH_TX_EN_Pin ); + HAL_GPIO_DeInit( ETH_TXD0_Port, ETH_TXD0_Pin ); + HAL_GPIO_DeInit( ETH_TXD1_Port, ETH_TXD1_Pin ); + + if( pxEthHandle->Init.MediaInterface == HAL_ETH_RMII_MODE ) + { + HAL_GPIO_DeInit( ETH_REF_CLK_Port, ETH_REF_CLK_Pin ); + HAL_GPIO_DeInit( ETH_CRS_DV_Port, ETH_CRS_DV_Pin ); + } + else if( pxEthHandle->Init.MediaInterface == HAL_ETH_MII_MODE ) + { + HAL_GPIO_DeInit( ETH_RX_CLK_Port, ETH_RX_CLK_Pin ); + HAL_GPIO_DeInit( ETH_RX_ER_Port, ETH_RX_ER_Pin ); + HAL_GPIO_DeInit( ETH_RX_DV_Port, ETH_RX_DV_Pin ); + HAL_GPIO_DeInit( ETH_RXD2_Port, ETH_RXD2_Pin ); + HAL_GPIO_DeInit( ETH_RXD3_Port, ETH_RXD3_Pin ); + HAL_GPIO_DeInit( ETH_TX_CLK_Port, ETH_TX_CLK_Pin ); + HAL_GPIO_DeInit( ETH_TXD2_Port, ETH_TXD2_Pin ); + HAL_GPIO_DeInit( ETH_TXD3_Port, ETH_TXD3_Pin ); + HAL_GPIO_DeInit( ETH_COL_Port, ETH_COL_Pin ); + HAL_GPIO_DeInit( ETH_CRS_Port, ETH_CRS_Pin ); + } - /* ETH interrupt Deinit */ - HAL_NVIC_DisableIRQ(ETH_IRQn); + /* ETH interrupt Deinit */ + HAL_NVIC_DisableIRQ( ETH_IRQn ); + } } -} /*---------------------------------------------------------------------------*/ -#if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) + #if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) -void MPU_Config(void) -{ - MPU_Region_InitTypeDef MPU_InitStruct = {0}; + void MPU_Config( void ) + { + MPU_Region_InitTypeDef MPU_InitStruct = { 0 }; - HAL_MPU_Disable(); + HAL_MPU_Disable(); - extern uint8_t __ETH_BUFFERS_START; + extern uint8_t __ETH_BUFFERS_START; - MPU_InitStruct.Enable = ipconfigIS_ENABLED( niEMAC_USE_MPU ) ? ENABLE : DISABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + MPU_InitStruct.Enable = ipconfigIS_ENABLED( niEMAC_USE_MPU ) ? ENABLE : DISABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_BUFFERS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_128KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); + HAL_MPU_ConfigRegion( &MPU_InitStruct ); - extern uint8_t __ETH_DESCRIPTORS_START; + extern uint8_t __ETH_DESCRIPTORS_START; - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; - MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; - MPU_InitStruct.SubRegionDisable = 0x0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.BaseAddress = ( uint32_t ) &__ETH_DESCRIPTORS_START; + MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - HAL_MPU_ConfigRegion(&MPU_InitStruct); + HAL_MPU_ConfigRegion( &MPU_InitStruct ); - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); -} + HAL_MPU_Enable( MPU_PRIVILEGED_DEFAULT ); + } -#endif /* if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) */ + #endif /* if defined( __MPU_PRESENT ) && ( __MPU_PRESENT == 1U ) */ #endif /* if 0 */ From 3a61d7f5c884f8635af756799860313b77febbac Mon Sep 17 00:00:00 2001 From: Holden Date: Tue, 6 Feb 2024 21:13:00 -0500 Subject: [PATCH 56/68] add spellings --- .github/.cSpellWords.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/.cSpellWords.txt b/.github/.cSpellWords.txt index 40ce1a0d60..227151d15e 100644 --- a/.github/.cSpellWords.txt +++ b/.github/.cSpellWords.txt @@ -228,6 +228,7 @@ DEFR Deglitchers DEMCR DEREN +Descs DEVAD DFREERTOS DFSR @@ -392,6 +393,8 @@ ETHERC ethernetif ETHMACRX ETHMACTX +ETHTX +ETHRX ETIE EVCNT EVCNTR @@ -439,6 +442,7 @@ FFSR FIFOSZ FLMSK FMAC +FNUM FOLDEVTENA FORCEWT FORWARDALLEXCEPTPA @@ -474,6 +478,14 @@ Gpbs GPCNTRL gpio GPIO +GPIOA +GPIOB +GPIOC +GPIOD +GPIOE +GPIOF +GPIOG +GPIOH GPSL GPSLCE gptimer @@ -589,6 +601,7 @@ IVLTV IVTIR JABBR JFRAME +Jndex jscott jscotts karkhaz @@ -673,6 +686,7 @@ MACECR MACFCR MACHT MACHTLR +MACHWF MACIMR MACISR MACMDIOAR @@ -1311,6 +1325,7 @@ TBFT TBQB TBQBAPQ TBUE +TBUS TCKER TCMSSV TCOMP From 5bed226560ad69157850a1ba6d04571f52fc9928 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Wed, 7 Feb 2024 02:15:43 +0000 Subject: [PATCH 57/68] Uncrustify: triggered by comment. --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 1032c2718b..c7dd9f8b3a 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -665,7 +665,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, UDPPacket_t * const pxUDPPacket = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; ( void ) pxUDPPacket; } - #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ + #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv4\n" ) ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ } @@ -706,7 +706,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, UDPPacket_t * const pxUDPPacket_IPv6 = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; ( void ) pxUDPPacket_IPv6; } - #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ + #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv6\n" ) ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ } @@ -864,7 +864,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, } pxEndDescriptor = pxCurDescriptor; - #else /* if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) */ + #else /* if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) */ prvSendRxEvent( pxCurDescriptor ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_LINKED_RX_MESSAGES ) */ } @@ -1021,7 +1021,7 @@ static BaseType_t prvEMACTaskStart( NetworkInterface_t * pxInterface ) uxEMACTaskStack, &xEMACTaskTCB ); - #else /* if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) */ + #else /* if ipconfigIS_ENABLED( configSUPPORT_STATIC_ALLOCATION ) */ ( void ) xTaskCreate( prvEMACHandlerTask, niEMAC_TASK_NAME, From 6bda6e0b7f9b6e1f1accabc58b46ad60493d9755 Mon Sep 17 00:00:00 2001 From: Mikhail Paulyshka Date: Mon, 12 Feb 2024 18:43:53 +0300 Subject: [PATCH 58/68] remove xCheckLoopback() usage --- .../portable/NetworkInterface/STM32/NetworkInterface.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index c7dd9f8b3a..2e63cbd764 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -590,16 +590,6 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, break; } - if( xCheckLoopback( pxDescriptor, xReleaseAfterSend ) != pdFALSE ) - { - /* The packet has been sent back to the IP-task. - * The IP-task will further handle it. - * Do not release the descriptor. */ - xReleaseAfterSend = pdFALSE; - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Loopback\n" ) ); - break; - } - if( prvGetPhyLinkStatus( pxInterface ) == pdFALSE ) { FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Link Down\n" ) ); From 99c8c036a770fe749b9db8731f8237b006239798 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 12 Feb 2024 18:56:53 -0500 Subject: [PATCH 59/68] Fix Phy function return value --- .../NetworkInterface/STM32/NetworkInterface.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index c7dd9f8b3a..f8f83ae01d 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -434,11 +434,11 @@ static BaseType_t prvPhyReadReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t * pulValue ) { - BaseType_t xResult = pdFALSE; + BaseType_t xResult = 0; - if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) == HAL_OK ) + if( HAL_ETH_ReadPHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, pulValue ) != HAL_OK ) { - xResult = pdTRUE; + xResult = -1; } return xResult; @@ -450,11 +450,11 @@ static BaseType_t prvPhyWriteReg( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue ) { - BaseType_t xResult = pdFALSE; + BaseType_t xResult = 0; - if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) == HAL_OK ) + if( HAL_ETH_WritePHYRegister( &xEthHandle, ( uint32_t ) xAddress, ( uint32_t ) xRegister, ulValue ) != HAL_OK ) { - xResult = pdTRUE; + xResult = -1; } return xResult; From 004ca898c04a2098982518d249020f8ef507e3b8 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 8 Apr 2024 16:17:08 -0400 Subject: [PATCH 60/68] Revert ND changes --- source/FreeRTOS_ND.c | 2 +- source/include/FreeRTOS_ND.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/source/FreeRTOS_ND.c b/source/FreeRTOS_ND.c index a084059896..d5c55e478e 100644 --- a/source/FreeRTOS_ND.c +++ b/source/FreeRTOS_ND.c @@ -1187,7 +1187,7 @@ pxICMPPacket = ( ( ICMPPacket_IPv6_t * ) pxNetworkBuffer->pucEthernetBuffer ); pxICMPHeader_IPv6 = ( ( ICMPHeader_IPv6_t * ) &( pxICMPPacket->xICMPHeaderIPv6 ) ); - ( void ) memcpy( pxICMPPacket->xEthernetHeader.xDestinationAddress.ucBytes, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ); + ( void ) memcpy( pxICMPPacket->xEthernetHeader.xDestinationAddress.ucBytes, pcLOCAL_ALL_NODES_MULTICAST_MAC, ipMAC_ADDRESS_LENGTH_BYTES ); ( void ) memcpy( pxICMPPacket->xEthernetHeader.xSourceAddress.ucBytes, pxEndPoint->xMACAddress.ucBytes, ipMAC_ADDRESS_LENGTH_BYTES ); pxICMPPacket->xEthernetHeader.usFrameType = ipIPv6_FRAME_TYPE; /* 12 + 2 = 14 */ diff --git a/source/include/FreeRTOS_ND.h b/source/include/FreeRTOS_ND.h index aa62c94099..d0f1685313 100644 --- a/source/include/FreeRTOS_ND.h +++ b/source/include/FreeRTOS_ND.h @@ -61,9 +61,6 @@ uint8_t ucValid; /**< pdTRUE: xMACAddress is valid, pdFALSE: waiting for ND reply */ } NDCacheRow_t; -/** @brief All nodes on the local network segment: MAC address 33:33:00:00:00:01. */ - extern const MACAddress_t pcLOCAL_ALL_NODES_MULTICAST_MAC; - /* * If ulIPAddress is already in the ND cache table then reset the age of the * entry back to its maximum value. If ulIPAddress is not already in the ND From 17a0021024b480583bcaee3fd1569acfb6fdaee1 Mon Sep 17 00:00:00 2001 From: Holden Date: Mon, 8 Apr 2024 16:21:16 -0400 Subject: [PATCH 61/68] Enable MAC filtering Netif functions --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 9ff320c399..8bf5333a99 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1062,7 +1062,6 @@ static BaseType_t prvEthConfigInit( ETH_HandleTypeDef * pxEthHandle, if( pxEndPoint != NULL ) { - /* ipLOCAL_MAC_ADDRESS */ pxEthHandle->Init.MACAddr = ( uint8_t * ) pxEndPoint->xMACAddress.ucBytes; if( HAL_ETH_Init( pxEthHandle ) == HAL_OK ) @@ -1822,7 +1821,7 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes } #ifdef niEMAC_STM32HX - else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_IGMP ) /* IGMP */ + else if( ( ulRxDesc & ETH_IP_PAYLOAD_MASK ) == ETH_IP_PAYLOAD_IGMP ) { } #endif @@ -2076,8 +2075,8 @@ NetworkInterface_t * pxSTM32_FillInterfaceDescriptor( BaseType_t xEMACIndex, pxInterface->pfOutput = prvNetworkInterfaceOutput; pxInterface->pfGetPhyLinkStatus = prvGetPhyLinkStatus; - /* pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; - * pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; */ + pxInterface->pfAddAllowedMAC = prvAddAllowedMACAddress; + pxInterface->pfRemoveAllowedMAC = prvRemoveAllowedMACAddress; return FreeRTOS_AddNetworkInterface( pxInterface ); } From 1728ba02e93c81a8e33a814272531359be53f826 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 6 Jun 2024 11:19:55 -0400 Subject: [PATCH 62/68] Add Current HAL Drivers --- .../STM32/Drivers/F4/stm32f4xx_hal_eth.c | 3221 ++++++++++++++++ .../STM32/Drivers/F4/stm32f4xx_hal_eth.h | 2019 ++++++++++ .../STM32/Drivers/F7/stm32f7xx_hal_eth.c | 3238 ++++++++++++++++ .../STM32/Drivers/F7/stm32f7xx_hal_eth.h | 2017 ++++++++++ .../STM32/Drivers/H5/stm32h5xx_hal_eth.c | 3341 ++++++++++++++++ .../STM32/Drivers/H5/stm32h5xx_hal_eth.h | 1823 +++++++++ .../STM32/Drivers/H5/stm32h5xx_hal_eth_ex.c | 660 ++++ .../STM32/Drivers/H5/stm32h5xx_hal_eth_ex.h | 366 ++ .../STM32/Drivers/H7/stm32h7xx_hal_eth.c | 3379 +++++++++++++++++ .../STM32/Drivers/H7/stm32h7xx_hal_eth.h | 1849 +++++++++ .../STM32/Drivers/H7/stm32h7xx_hal_eth_ex.c | 660 ++++ .../STM32/Drivers/H7/stm32h7xx_hal_eth_ex.h | 366 ++ 12 files changed, 22939 insertions(+) create mode 100644 source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.h create mode 100644 source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.h create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.h create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.h create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.h create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.c create mode 100644 source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.h diff --git a/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.c b/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.c new file mode 100644 index 0000000000..df3ccc65c8 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.c @@ -0,0 +1,3221 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and deinitialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The ETH HAL driver can be used as follows: + + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE() + (+++) __HAL_RCC_ETH1TX_CLK_ENABLE() + (+++) __HAL_RCC_ETH1RX_CLK_ENABLE() + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pinout + (##) Configure Ethernet NVIC interrupt (in Interrupt mode) + + (#) Ethernet data reception is asynchronous, so call the following API + to start the listening mode: + (##) HAL_ETH_Start(): + This API starts the MAC and DMA transmission and reception process, + without enabling end of transfer interrupts, in this mode user + has to poll for data reception by calling HAL_ETH_ReadData() + (##) HAL_ETH_Start_IT(): + This API starts the MAC and DMA transmission and reception process, + end of transfer interrupts are enabled in this mode, + HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received + + (#) When data is received user can call the following API to get received data: + (##) HAL_ETH_ReadData(): Read a received packet + + (#) For transmission path, two APIs are available: + (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode + (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode, + HAL_ETH_TxCpltCallback() will be executed when end of transfer occur + + (#) Communication with an external PHY device: + (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY + (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register + + (#) Configure the Ethernet MAC after ETH peripheral initialization + (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef + (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef + + (#) Configure the Ethernet DMA after ETH peripheral initialization + (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef + (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef + + (#) Configure the Ethernet PTP after ETH peripheral initialization + (##) Define HAL_ETH_USE_PTP to use PTP APIs. + (##) HAL_ETH_PTP_GetConfig(): Get PTP actual configuration into ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_SetConfig(): Set PTP configuration based on ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_GetTime(): Get Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_SetTime(): Set Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_AddTimeOffset(): Add Seconds and Nanoseconds offset for the Ethernet PTP registers + (##) HAL_ETH_PTP_InsertTxTimestamp(): Insert Timestamp in transmission + (##) HAL_ETH_PTP_GetTxTimestamp(): Get transmission timestamp + (##) HAL_ETH_PTP_GetRxTimestamp(): Get reception timestamp + + -@- The ARP offload feature is not supported in this driver. + + -@- The PTP offload feature is not supported in this driver. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callbacks RxAllocateCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxPtpCallback(). + + Use function HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + For specific callbacks RxAllocateCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxPtpCallback(). + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ETH_TxCpltCallback(), HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_ETH_RegisterCallback() before calling HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_MACCR_MASK 0xFFFB7F7CU +#define ETH_MACECR_MASK 0x3F077FFFU +#define ETH_MACFFR_MASK 0x800007FFU +#define ETH_MACWTR_MASK 0x0000010FU +#define ETH_MACTFCR_MASK 0xFFFF00F2U +#define ETH_MACRFCR_MASK 0x00000003U +#define ETH_MTLTQOMR_MASK 0x00000072U +#define ETH_MTLRQOMR_MASK 0x0000007BU + +#define ETH_DMAMR_MASK 0x00007802U +#define ETH_DMASBMR_MASK 0x0000D001U +#define ETH_DMACCR_MASK 0x00013FFFU +#define ETH_DMACTCR_MASK 0x003F1010U +#define ETH_DMACRCR_MASK 0x803F0000U +#define ETH_MACPMTCSR_MASK (ETH_MACPMTCSR_PD | ETH_MACPMTCSR_WFE | \ + ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU) + +/* Timeout values */ +#define ETH_SWRESET_TIMEOUT 500U +#define ETH_MDIO_BUS_TIMEOUT 1000U + +#define ETH_DMARXDESC_ERRORS_MASK ((uint32_t)(ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | \ + ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT |\ + ETH_DMARXDESC_LC | ETH_DMARXDESC_CE |\ + ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE)) + +#define ETH_MAC_US_TICK 1000000U + +#define ETH_MACTSCR_MASK 0x0087FF2FU + +#define ETH_PTPTSHR_VALUE 0xFFFFFFFFU +#define ETH_PTPTSLR_VALUE 0xBB9ACA00U + +/* Ethernet MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/* Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY 0x00000001U + +/* ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFF20810FU + +/* ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/* ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (uint32_t)(ETH_MAC_BASE + 0x40U) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (uint32_t)(ETH_MAC_BASE + 0x44U) /* ETHERNET MAC address low offset */ + +/* ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Macros ETH Private Macros + * @{ + */ +/* Helper macros for TX descriptor handling */ +#define INCR_TX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\ + } while (0) + +/* Helper macros for RX descriptor handling */ +#define INCR_RX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\ + } while (0) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth); +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth); +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth); +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode); +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth); +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth); +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the ETH peripheral: + + (+) User must Implement HAL_ETH_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO and NVIC ). + + (+) Call the function HAL_ETH_Init() to configure the selected device with + the selected configuration: + (++) MAC address + (++) Media interface (MII or RMII) + (++) Rx DMA Descriptors Tab + (++) Tx DMA Descriptors Tab + (++) Length of Rx Buffers + + (+) Call the function HAL_ETH_DeInit() to restore the default configuration + of the selected ETH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the Ethernet peripheral registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tickstart; + + if (heth == NULL) + { + return HAL_ERROR; + } + if (heth->gState == HAL_ETH_STATE_RESET) + { + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + ETH_InitCallbacksToDefault(heth); + + if (heth->MspInitCallback == NULL) + { + heth->MspInitCallback = HAL_ETH_MspInit; + } + + /* Init the low level hardware */ + heth->MspInitCallback(heth); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + } + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Select MII or RMII Mode*/ + SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL); + SYSCFG->PMC |= (uint32_t)heth->Init.MediaInterface; + /* Dummy read to sync SYSCFG with ETH */ + (void)SYSCFG->PMC; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + SET_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + } + + + /*------------------ MAC, MTL and DMA default Configuration ----------------*/ + ETH_MACDMAConfig(heth); + + + /*------------------ DMA Tx Descriptors Configuration ----------------------*/ + ETH_DMATxDescListInit(heth); + + /*------------------ DMA Rx Descriptors Configuration ----------------------*/ + ETH_DMARxDescListInit(heth); + + /*--------------------- ETHERNET MAC Address Configuration ------------------*/ + ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr); + + /* Disable MMC Interrupts */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM); + + /* Disable Rx MMC Interrupts */ + SET_BIT(heth->Instance->MMCRIMR, ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | \ + ETH_MMCRIMR_RFCEM); + + /* Disable Tx MMC Interrupts */ + SET_BIT(heth->Instance->MMCTIMR, ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | \ + ETH_MMCTIMR_TGFSCM); + + heth->ErrorCode = HAL_ETH_ERROR_NONE; + heth->gState = HAL_ETH_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the ETH peripheral. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + if (heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* DeInit the low level hardware */ + heth->MspDeInitCallback(heth); +#else + + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + + /* Set ETH HAL state to Disabled */ + heth->gState = HAL_ETH_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = pCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = pCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callback is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = HAL_ETH_PMTCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief ETH Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the ETH + data transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables Ethernet MAC and DMA reception and transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + heth->gState = HAL_ETH_STATE_STARTED; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* save IT mode to ETH Handle */ + heth->RxDescList.ItMode = 1U; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Enable ETH DMA interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + heth->gState = HAL_ETH_STATE_STARTED; + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t descindex; + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Clear IOC bit to all Rx descriptors */ + for (descindex = 0; descindex < (uint32_t)ETH_RX_DESC_CNT; descindex++) + { + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex]; + SET_BIT(dmarxdesc->DESC1, ETH_DMARXDESC_DIC); + } + + heth->RxDescList.ItMode = 0U; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in polling mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @param Timeout: timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout) +{ + uint32_t tickstart; + ETH_DMADescTypeDef *dmatxdesc; + + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE) + { + /* Set the ETH error code */ + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc]; + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMATPDR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + tickstart = HAL_GetTick(); + + /* Wait for data to be transmitted or timeout occurred */ + while ((dmatxdesc->DESC0 & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + if ((heth->Instance->DMASR & ETH_DMASR_FBES) != (uint32_t)RESET) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + heth->DMAErrorCode = heth->Instance->DMASR; + /* Return function status */ + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT; + /* Clear TX descriptor so that we can proceed */ + dmatxdesc->DESC0 = (ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + return HAL_ERROR; + } + } + } + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in interrupt mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig) +{ + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Save the packet pointer to release. */ + heth->TxDescList.CurrentPacketAddress = (uint32_t *)pTxConfig->pData; + + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE) + { + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + (heth->Instance)->DMASR = ETH_DMASR_TBUS; + /* Resume DMA transmission*/ + (heth->Instance)->DMATPDR = 0U; + } + + return HAL_OK; + + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Read a received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pAppBuff: Pointer to an application buffer to receive the packet. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff) +{ + uint32_t descidx; + ETH_DMADescTypeDef *dmarxdesc; + uint32_t desccnt = 0U; + uint32_t desccntmax; + uint32_t bufflength; + uint8_t rxdataready = 0U; + + if (pAppBuff == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState != HAL_ETH_STATE_STARTED) + { + return HAL_ERROR; + } + + descidx = heth->RxDescList.RxDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccntmax = ETH_RX_DESC_CNT - heth->RxDescList.RxBuildDescCnt; + + /* Check if descriptor is not owned by DMA */ + while ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (desccnt < desccntmax) + && (rxdataready == 0U)) + { + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Get timestamp high */ + heth->RxDescList.TimeStamp.TimeStampHigh = dmarxdesc->DESC7; + /* Get timestamp low */ + heth->RxDescList.TimeStamp.TimeStampLow = dmarxdesc->DESC6; + } + if ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) || (heth->RxDescList.pRxStart != NULL)) + { + /* Check first descriptor */ + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) + { + heth->RxDescList.RxDescCnt = 0; + heth->RxDescList.RxDataLength = 0; + } + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + bufflength = ((dmarxdesc->DESC0 & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U; + + /* Check if last descriptor */ + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Save Last descriptor index */ + heth->RxDescList.pRxLastRxDesc = dmarxdesc->DESC0; + + /* Packet ready */ + rxdataready = 1; + } + + /* Link data */ + WRITE_REG(dmarxdesc->BackupAddr0, dmarxdesc->DESC2); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Link callback*/ + heth->rxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, bufflength); +#else + /* Link callback */ + HAL_ETH_RxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, (uint16_t) bufflength); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->RxDescList.RxDescCnt++; + heth->RxDescList.RxDataLength += bufflength; + + /* Clear buffer pointer */ + dmarxdesc->BackupAddr0 = 0; + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccnt++; + } + + heth->RxDescList.RxBuildDescCnt += desccnt; + if ((heth->RxDescList.RxBuildDescCnt) != 0U) + { + /* Update Descriptors */ + ETH_UpdateDescriptor(heth); + } + + heth->RxDescList.RxDescIdx = descidx; + + if (rxdataready == 1U) + { + /* Return received packet */ + *pAppBuff = heth->RxDescList.pRxStart; + /* Reset first element */ + heth->RxDescList.pRxStart = NULL; + + return HAL_OK; + } + + /* Packet not ready */ + return HAL_ERROR; +} + +/** + * @brief This function gives back Rx Desc of the last received Packet + * to the DMA, so ETH DMA will be able to use these descriptors + * to receive next Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth) +{ + uint32_t tailidx; + uint32_t descidx; + uint32_t desccount; + ETH_DMADescTypeDef *dmarxdesc; + uint8_t *buff = NULL; + uint8_t allocStatus = 1U; + + descidx = heth->RxDescList.RxBuildDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount = heth->RxDescList.RxBuildDescCnt; + + while ((desccount > 0U) && (allocStatus != 0U)) + { + /* Check if a buffer's attached the descriptor */ + if (READ_REG(dmarxdesc->BackupAddr0) == 0U) + { + /* Get a new buffer. */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Allocate callback*/ + heth->rxAllocateCallback(&buff); +#else + /* Allocate callback */ + HAL_ETH_RxAllocateCallback(&buff); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + if (buff == NULL) + { + allocStatus = 0U; + } + else + { + WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)buff); + WRITE_REG(dmarxdesc->DESC2, (uint32_t)buff); + } + } + + if (allocStatus != 0U) + { + if (heth->RxDescList.ItMode == 0U) + { + WRITE_REG(dmarxdesc->DESC1, ETH_DMARXDESC_DIC | ETH_RX_BUF_SIZE | ETH_DMARXDESC_RCH); + } + else + { + WRITE_REG(dmarxdesc->DESC1, ETH_RX_BUF_SIZE | ETH_DMARXDESC_RCH); + } + + SET_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN); + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount--; + } + } + + if (heth->RxDescList.RxBuildDescCnt != desccount) + { + /* Set the tail pointer index */ + tailidx = (descidx + 1U) % ETH_RX_DESC_CNT; + + /* DMB instruction to avoid race condition */ + __DMB(); + + /* Set the Tail pointer address */ + WRITE_REG(heth->Instance->DMARPDR, ((uint32_t)(heth->Init.RxDesc + (tailidx)))); + + heth->RxDescList.RxBuildDescIdx = descidx; + heth->RxDescList.RxBuildDescCnt = desccount; + } +} + +/** + * @brief Register the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxAllocateCallback: pointer to function to alloc buffer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback) +{ + if (rxAllocateCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to allocate buffer */ + heth->rxAllocateCallback = rxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Rx Allocate callback. + * @param buff: pointer to allocated buffer + * @retval None + */ +__weak void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxAllocateCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Link callback. + * @param pStart: pointer to packet start + * @param pEnd: pointer to packet end + * @param buff: pointer to received data + * @param Length: received data length + * @retval None + */ +__weak void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(pStart); + UNUSED(pEnd); + UNUSED(buff); + UNUSED(Length); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxLinkCallback could be implemented in the user file + */ +} + +/** + * @brief Set the Rx link data function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxLinkCallback: pointer to function to link data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback) +{ + if (rxLinkCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to link data */ + heth->rxLinkCallback = rxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx link callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Get the error state of the last received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pErrorCode: pointer to uint32_t to hold the error code + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode) +{ + /* Get error bits. */ + *pErrorCode = READ_BIT(heth->RxDescList.pRxLastRxDesc, ETH_DMARXDESC_ERRORS_MASK); + + return HAL_OK; +} + +/** + * @brief Set the Tx free function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txFreeCallback: pointer to function to release the packet + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback) +{ + if (txFreeCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to free transmmitted packet */ + heth->txFreeCallback = txFreeCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx free callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; + + return HAL_OK; +} + +/** + * @brief Tx Free callback. + * @param buff: pointer to buffer to free + * @retval None + */ +__weak void HAL_ETH_TxFreeCallback(uint32_t *buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxFreeCallback could be implemented in the user file + */ +} + +/** + * @brief Release transmitted Tx packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t numOfBuf = dmatxdesclist->BuffersInUse; + uint32_t idx = dmatxdesclist->releaseIndex; + uint8_t pktTxStatus = 1U; + uint8_t pktInUse; +#ifdef HAL_ETH_USE_PTP + ETH_TimeStampTypeDef *timestamp = &heth->TxTimestamp; +#endif /* HAL_ETH_USE_PTP */ + + /* Loop through buffers in use. */ + while ((numOfBuf != 0U) && (pktTxStatus != 0U)) + { + pktInUse = 1U; + numOfBuf--; + /* If no packet, just examine the next packet. */ + if (dmatxdesclist->PacketAddress[idx] == NULL) + { + /* No packet in use, skip to next. */ + idx = (idx + 1U) & (ETH_TX_DESC_CNT - 1U); + pktInUse = 0U; + } + + if (pktInUse != 0U) + { + /* Determine if the packet has been transmitted. */ + if ((heth->Init.TxDesc[idx].DESC0 & ETH_DMATXDESC_OWN) == 0U) + { +#ifdef HAL_ETH_USE_PTP + /* Get timestamp low */ + timestamp->TimeStampLow = heth->Init.TxDesc[idx].DESC6; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->Init.TxDesc[idx].DESC7; +#endif /* HAL_ETH_USE_PTP */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered callbacks*/ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + heth->txPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + heth->txFreeCallback(dmatxdesclist->PacketAddress[idx]); +#else + /* Call callbacks */ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + HAL_ETH_TxPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + HAL_ETH_TxFreeCallback(dmatxdesclist->PacketAddress[idx]); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the entry in the in-use array. */ + dmatxdesclist->PacketAddress[idx] = NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + idx = (idx + 1U) & (ETH_TX_DESC_CNT - 1U); + dmatxdesclist->BuffersInUse = numOfBuf; + dmatxdesclist->releaseIndex = idx; + } + else + { + /* Get out of the loop! */ + pktTxStatus = 0U; + } + } + } + return HAL_OK; +} + +#ifdef HAL_ETH_USE_PTP +/** + * @brief Set the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + uint32_t tmpTSCR; + ETH_TimeTypeDef time; + + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + + tmpTSCR = ptpconfig->Timestamp | + ((uint32_t)ptpconfig->TimestampUpdate << ETH_PTPTSCR_TSFCU_Pos) | + ((uint32_t)ptpconfig->TimestampAll << ETH_PTPTSCR_TSSARFE_Pos) | + ((uint32_t)ptpconfig->TimestampRolloverMode << ETH_PTPTSCR_TSSSR_Pos) | + ((uint32_t)ptpconfig->TimestampV2 << ETH_PTPTSCR_TSPTPPSV2E_Pos) | + ((uint32_t)ptpconfig->TimestampEthernet << ETH_PTPTSCR_TSSPTPOEFE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv6 << ETH_PTPTSCR_TSSIPV6FE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv4 << ETH_PTPTSCR_TSSIPV4FE_Pos) | + ((uint32_t)ptpconfig->TimestampEvent << ETH_PTPTSCR_TSSEME_Pos) | + ((uint32_t)ptpconfig->TimestampMaster << ETH_PTPTSCR_TSSMRME_Pos) | + ((uint32_t)ptpconfig->TimestampFilter << ETH_PTPTSCR_TSPFFMAE_Pos) | + ((uint32_t)ptpconfig->TimestampClockType << ETH_PTPTSCR_TSCNT_Pos); + + /* Write to MACTSCR */ + MODIFY_REG(heth->Instance->PTPTSCR, ETH_MACTSCR_MASK, tmpTSCR); + + /* Enable Timestamp */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + WRITE_REG(heth->Instance->PTPSSIR, ptpconfig->TimestampSubsecondInc); + WRITE_REG(heth->Instance->PTPTSAR, ptpconfig->TimestampAddend); + + /* Enable Timestamp */ + if (ptpconfig->TimestampAddendUpdate == ENABLE) + { + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSARU); + while ((heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU) != 0) {} + } + + /* Enable Update mode */ + if (ptpconfig->TimestampUpdateMode == ENABLE) + { + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSFCU); + } + + /* Initialize Time */ + time.Seconds = 0; + time.NanoSeconds = 0; + HAL_ETH_PTP_SetTime(heth, &time); + + /* Ptp Init */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSTI); + + /* Set PTP Configuration done */ + heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURATED; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Get the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + ptpconfig->Timestamp = READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + ptpconfig->TimestampUpdate = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSFCU) >> ETH_PTPTSCR_TSFCU_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampAll = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSARFE) >> ETH_PTPTSCR_TSSARFE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampRolloverMode = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSSR) >> ETH_PTPTSCR_TSSSR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampV2 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPTPPSV2E) >> ETH_PTPTSCR_TSPTPPSV2E_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEthernet = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSPTPOEFE) >> ETH_PTPTSCR_TSSPTPOEFE_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampIPv6 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV6FE) >> ETH_PTPTSCR_TSSIPV6FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv4 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV4FE) >> ETH_PTPTSCR_TSSIPV4FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEvent = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSEME) >> ETH_PTPTSCR_TSSEME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampMaster = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSMRME) >> ETH_PTPTSCR_TSSMRME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampFilter = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPFFMAE) >> ETH_PTPTSCR_TSPFFMAE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampClockType = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSCNT) >> ETH_PTPTSCR_TSCNT_Pos) > 0U) ? ENABLE : DISABLE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param heth: pointer to a ETH_TimeTypeDef structure that contains + * time to set + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Set Seconds */ + heth->Instance->PTPTSHUR = time->Seconds; + + /* Set NanoSeconds */ + heth->Instance->PTPTSLUR = time->NanoSeconds; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param heth: pointer to a ETH_TimeTypeDef structure that contains + * time to get + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get Seconds */ + time->Seconds = heth->Instance->PTPTSHR; + + /* Get NanoSeconds */ + time->NanoSeconds = heth->Instance->PTPTSLR; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Update time for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timeupdate: pointer to a ETH_TIMEUPDATETypeDef structure that contains + * the time update information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + if (ptpoffsettype == HAL_ETH_PTP_NEGATIVE_UPDATE) + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = ETH_PTPTSHR_VALUE - timeoffset->Seconds + 1U; + + if (READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSSR) == ETH_PTPTSCR_TSSSR) + { + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = ETH_PTPTSLR_VALUE - timeoffset->NanoSeconds; + } + else + { + heth->Instance->PTPTSLUR = ETH_PTPTSHR_VALUE - timeoffset->NanoSeconds + 1U; + } + } + else + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = timeoffset->Seconds; + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = timeoffset->NanoSeconds; + } + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Insert Timestamp in transmission. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txtimestampconf: Enable or Disable timestamp in transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Enable Time Stamp transmission */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TTSE); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get transmission timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * transmission timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t idx = dmatxdesclist->releaseIndex; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[idx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = dmatxdesc->DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = dmatxdesc->DESC1; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get receive timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * receive timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURATED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->RxDescList.TimeStamp.TimeStampLow; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->RxDescList.TimeStamp.TimeStampHigh; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Register the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txPtpCallback: Function to handle Ptp transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback) +{ + if (txPtpCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + /* Set Function to handle Tx Ptp */ + heth->txPtpCallback = txPtpCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txPtpCallback = HAL_ETH_TxPtpCallback; + + return HAL_OK; +} + +/** + * @brief Tx Ptp callback. + * @param buff: pointer to application buffer + * @retval None + */ +__weak void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxPtpCallback could be implemented in the user file + */ +} +#endif /* HAL_ETH_USE_PTP */ + +/** + * @brief This function handles ETH interrupt request. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + /* Packet received */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_RS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_RIE)) + { + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_RS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } + + /* Packet transmitted */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_TS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_TIE)) + { + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_TS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Transmit complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } + + /* ETH DMA Error */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_AIS)) + { + if (__HAL_ETH_DMA_GET_IT_SOURCE(heth, ETH_DMAIER_AISE)) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + /* if fatal bus error occurred */ + if (__HAL_ETH_DMA_GET_IT(heth, ETH_DMASR_FBES)) + { + /* Get DMA error code */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS)); + + /* Disable all interrupts */ + __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMAIER_NISE | ETH_DMAIER_AISE); + + /* Set HAL state to ERROR */ + heth->gState = HAL_ETH_STATE_ERROR; + } + else + { + /* Get DMA error status */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + + /* Clear the interrupt summary flag */ + __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + } +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet DMA Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + } + } + + + /* ETH PMT IT */ + if (__HAL_ETH_MAC_GET_IT(heth, ETH_MAC_PMT_IT)) + { + /* Get MAC Wake-up source and clear the status register pending bit */ + heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPMTCSR, (ETH_MACPMTCSR_WFR | ETH_MACPMTCSR_MPR)); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered PMT callback*/ + heth->PMTCallback(heth); +#else + /* Ethernet PMT callback */ + HAL_ETH_PMTCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACWakeUpEvent = (uint32_t)(0x0U); + } + + + /* check ETH WAKEUP exti flag */ + if (__HAL_ETH_WAKEUP_EXTI_GET_FLAG(ETH_WAKEUP_EXTI_LINE) != (uint32_t)RESET) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet Power Management module IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_PMTCallback could be implemented in the user file + */ +} + + +/** + * @brief ETH WAKEUP interrupt callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_WakeUpCallback could be implemented in the user file + */ +} + +/** + * @brief Read a PHY register + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param pRegValue: parameter to hold read value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII address register value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_READ_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + /* Get MACMIIDR value */ + *pRegValue = (uint16_t)(heth->Instance->MACMIIDR); + + return HAL_OK; +} + + +/** + * @brief Writes to a PHY register. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param RegValue: the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII register address value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Give the value to the MII data register */ + heth->Instance->MACMIIDR = (uint16_t)RegValue; + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_WRITE_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief ETH control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the ETH + peripheral. + +@endverbatim + * @{ + */ +/** + * @brief Get the configuration of the MAC and MTL subsystems. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold + * the configuration of the MAC. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + /* Get MAC parameters */ + macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL); + macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_RD) >> 9) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CSD) >> 16) > 0U) + ? ENABLE : DISABLE; + macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ROD) >> 13) == 0U) ? ENABLE : DISABLE; + macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE; + macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM); + macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES); + macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >> 22) == 0U) ? ENABLE : DISABLE; + macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >> 23) == 0U) ? ENABLE : DISABLE; + macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_APCS) >> 7) > 0U) ? ENABLE : DISABLE; + macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IFG); + macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPCO) >> 10U) > 0U) ? ENABLE : DISABLE; + + + macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_TFCE) >> 1) > 0U) ? ENABLE : DISABLE; + macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_ZQPD) >> 7) == 0U) ? ENABLE : DISABLE; + macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PLT); + macconf->PauseTime = (READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PT) >> 16); + macconf->ReceiveFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_RFCE) >> 2U) > 0U) ? ENABLE : DISABLE; + macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_UPFD) >> 3U) > 0U) + ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Get the configuration of the DMA. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMABMR, + (ETH_DMAARBITRATION_RXPRIORTX | ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1)); + dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_AAB) >> 25U) > 0U) ? ENABLE : DISABLE; + dmaconf->BurstMode = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_FB | ETH_DMABMR_MB); + dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_RDP); + dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_PBL); + dmaconf->EnhancedDescriptorFormat = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_EDE) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->DescriptorSkipLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_DSL) >> 2; + + dmaconf->DropTCPIPChecksumErrorFrame = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_DTCEFD) >> 26) > 0U) ? DISABLE : ENABLE; + dmaconf->ReceiveStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RSF) >> 25) > 0U) ? ENABLE : DISABLE; + dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FTF) >> 20) > 0U) ? DISABLE : ENABLE; + dmaconf->TransmitStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TSF) >> 21) > 0U) ? ENABLE : DISABLE; + dmaconf->TransmitThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TTC); + dmaconf->ForwardErrorFrames = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FEF) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->ForwardUndersizedGoodFrames = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_FUGF) >> 6) > 0U) ? ENABLE : DISABLE; + dmaconf->ReceiveThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RTC); + dmaconf->SecondFrameOperate = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_OSF) >> 2) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the MAC configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains + * the configuration of the MAC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetMACConfig(heth, macconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Set the ETH DMA configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetDMAConfig(heth, dmaconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configures the Clock range of ETH MDIO interface. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth) +{ + uint32_t hclk; + uint32_t tmpreg; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg = (heth->Instance)->MACMIIAR; + /* Clear CSR Clock Range CR[2:0] bits */ + tmpreg &= ETH_MACMIIAR_CR_MASK; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if ((hclk >= 20000000U) && (hclk < 35000000U)) + { + /* CSR Clock Range between 20-35 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div16; + } + else if ((hclk >= 35000000U) && (hclk < 60000000U)) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div26; + } + else if ((hclk >= 60000000U) && (hclk < 100000000U)) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42; + } + else if ((hclk >= 100000000U) && (hclk < 150000000U)) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div62; + } + else /* ((hclk >= 150000000)&&(hclk <= 183000000))*/ + { + /* CSR Clock Range between 150-183 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div102; + } + + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */ + (heth->Instance)->MACMIIAR = (uint32_t)tmpreg; +} + +/** + * @brief Set the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + uint32_t filterconfig; + uint32_t tmpreg1; + + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode | + ((uint32_t)pFilterConfig->HashUnicast << 1) | + ((uint32_t)pFilterConfig->HashMulticast << 2) | + ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) | + ((uint32_t)pFilterConfig->PassAllMulticast << 4) | + ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) | + ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) | + ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) | + ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) | + ((uint32_t)pFilterConfig->ReceiveAllMode << 31) | + pFilterConfig->ControlPacketsFilter); + + MODIFY_REG(heth->Instance->MACFFR, ETH_MACFFR_MASK, filterconfig); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFFR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFFR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Get the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PM)) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HU) >> 1) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HM) >> 2) > 0U) ? ENABLE : DISABLE; + pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE; + pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PAM) >> 4) > 0U) ? ENABLE : DISABLE; + pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_BFD) >> 5) == 0U) ? ENABLE : DISABLE; + pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PCF); + pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE; + pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HPF) >> 10) > 0U) + ? ENABLE : DISABLE; + pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_RA) >> 31) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the source MAC Address to be matched. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param AddrNbr: The MAC address to configure + * This parameter must be a value of the following: + * ETH_MAC_ADDRESS1 + * ETH_MAC_ADDRESS2 + * ETH_MAC_ADDRESS3 + * @param pMACAddr: Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr) +{ + uint32_t macaddrlr; + uint32_t macaddrhr; + + if (pMACAddr == NULL) + { + return HAL_ERROR; + } + + /* Get mac addr high reg offset */ + macaddrhr = ((uint32_t) &(heth->Instance->MACA0HR) + AddrNbr); + /* Get mac addr low reg offset */ + macaddrlr = ((uint32_t) &(heth->Instance->MACA0LR) + AddrNbr); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) | + ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= (ETH_MACA1HR_AE | ETH_MACA1HR_SA); + + return HAL_OK; +} + +/** + * @brief Set the ETH Hash Table Value. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pHashTable: pointer to a table of two 32 bit values, that contains + * the 64 bits of the hash table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable) +{ + uint32_t tmpreg1; + if (pHashTable == NULL) + { + return HAL_ERROR; + } + + heth->Instance->MACHTHR = pHashTable[0]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTHR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTHR = tmpreg1; + + heth->Instance->MACHTLR = pHashTable[1]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTLR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTLR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Identifier for Rx packets + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ComparisonBits: 12 or 16 bit comparison mode + must be a value of @ref ETH_VLAN_Tag_Comparison + * @param VLANIdentifier: VLAN Identifier value + * @retval None + */ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier) +{ + uint32_t tmpreg1; + MODIFY_REG(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTI, VLANIdentifier); + if (ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT) + { + CLEAR_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + else + { + SET_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACVLANTR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACVLANTR = tmpreg1; +} + +/** + * @brief Enters the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure + * that contains the Power Down configuration + * @retval None. + */ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, const ETH_PowerDownConfigTypeDef *pPowerDownConfig) +{ + uint32_t powerdownconfig; + + powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << ETH_MACPMTCSR_MPE_Pos) | + ((uint32_t)pPowerDownConfig->WakeUpPacket << ETH_MACPMTCSR_WFE_Pos) | + ((uint32_t)pPowerDownConfig->GlobalUnicast << ETH_MACPMTCSR_GU_Pos) | + ETH_MACPMTCSR_PD); + + MODIFY_REG(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_MASK, powerdownconfig); +} + +/** + * @brief Exits from the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + /* clear wake up sources */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFE | ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + + if (READ_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD) != 0U) + { + /* Exit power down mode */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + } + + /* Disable PMT interrupt */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_PMTIM); +} + +/** + * @brief Set the WakeUp filter. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilter: pointer to filter registers values + * @param Count: number of filter registers, must be from 1 to 8. + * @retval None. + */ +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count) +{ + uint32_t regindex; + + if (pFilter == NULL) + { + return HAL_ERROR; + } + + /* Reset Filter Pointer */ + SET_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFFRPR); + + /* Wake up packet filter config */ + for (regindex = 0; regindex < Count; regindex++) + { + /* Write filter regs */ + WRITE_REG(heth->Instance->MACRWUFFR, pFilter[regindex]); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief ETH State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + ETH communication process, return Peripheral Errors occurred during communication + process + + +@endverbatim + * @{ + */ + +/** + * @brief Returns the ETH state. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth) +{ + return heth->gState; +} + +/** + * @brief Returns the ETH error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH Error Code + */ +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth) +{ + return heth->ErrorCode; +} + +/** + * @brief Returns the ETH DMA error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH DMA Error Code + */ +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth) +{ + return heth->DMAErrorCode; +} + +/** + * @brief Returns the ETH MAC error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC Error Code + */ +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth) +{ + return heth->MACErrorCode; +} + +/** + * @brief Returns the ETH MAC WakeUp event source + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event source + */ +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth) +{ + return heth->MACWakeUpEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions ETH Private Functions + * @{ + */ + +/** + * @brief Clears the ETHERNET transmit FIFO. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg = 0; + + /* Set the Flush Transmit FIFO bit */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg; +} + +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + uint32_t tmpreg1; + + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + /* Clear WD, PCE, PS, TE and RE bits */ + tmpreg1 &= ETH_MACCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 23U) | + ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 22U) | + (uint32_t)macconf->InterPacketGapVal | + ((uint32_t)macconf->CarrierSenseDuringTransmit << 16U) | + macconf->Speed | + ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 13U) | + ((uint32_t)macconf->LoopbackMode << 12U) | + macconf->DuplexMode | + ((uint32_t)macconf->ChecksumOffload << 10U) | + ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 9U) | + ((uint32_t)macconf->AutomaticPadCRCStrip << 7U) | + macconf->BackOffLimit | + ((uint32_t)macconf->DeferralCheck << 4U)); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /*----------------------- ETHERNET MACFCR Configuration --------------------*/ + + /* Get the ETHERNET MACFCR value */ + tmpreg1 = (heth->Instance)->MACFCR; + /* Clear xx bits */ + tmpreg1 &= ETH_MACFCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) | + ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U) << 7U) | + macconf->PauseLowThreshold | + ((uint32_t)((macconf->UnicastPausePacketDetect == ENABLE) ? 1U : 0U) << 3U) | + ((uint32_t)((macconf->ReceiveFlowControl == ENABLE) ? 1U : 0U) << 2U) | + ((uint32_t)((macconf->TransmitFlowControl == ENABLE) ? 1U : 0U) << 1U)); + + /* Write to ETHERNET MACFCR */ + (heth->Instance)->MACFCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFCR = tmpreg1; +} + +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + uint32_t tmpreg1; + + /*----------------------- ETHERNET DMAOMR Configuration --------------------*/ + /* Get the ETHERNET DMAOMR value */ + tmpreg1 = (heth->Instance)->DMAOMR; + /* Clear xx bits */ + tmpreg1 &= ETH_DMAOMR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)((dmaconf->DropTCPIPChecksumErrorFrame == DISABLE) ? 1U : 0U) << 26U) | + ((uint32_t)dmaconf->ReceiveStoreForward << 25U) | + ((uint32_t)((dmaconf->FlushRxPacket == DISABLE) ? 1U : 0U) << 20U) | + ((uint32_t)dmaconf->TransmitStoreForward << 21U) | + dmaconf->TransmitThresholdControl | + ((uint32_t)dmaconf->ForwardErrorFrames << 7U) | + ((uint32_t)dmaconf->ForwardUndersizedGoodFrames << 6U) | + dmaconf->ReceiveThresholdControl | + ((uint32_t)dmaconf->SecondFrameOperate << 2U)); + + /* Write to ETHERNET DMAOMR */ + (heth->Instance)->DMAOMR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; + + /*----------------------- ETHERNET DMABMR Configuration --------------------*/ + (heth->Instance)->DMABMR = (uint32_t)(((uint32_t)dmaconf->AddressAlignedBeats << 25U) | + dmaconf->BurstMode | + dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or + Rx it is applied for the other */ + dmaconf->TxDMABurstLength | + ((uint32_t)dmaconf->EnhancedDescriptorFormat << 7U) | + (dmaconf->DescriptorSkipLength << 2U) | + dmaconf->DMAArbitration | + ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMABMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMABMR = tmpreg1; +} + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth) +{ + ETH_MACConfigTypeDef macDefaultConf; + ETH_DMAConfigTypeDef dmaDefaultConf; + + /*--------------- ETHERNET MAC registers default Configuration --------------*/ + macDefaultConf.Watchdog = ENABLE; + macDefaultConf.Jabber = ENABLE; + macDefaultConf.InterPacketGapVal = ETH_INTERFRAMEGAP_96BIT; + macDefaultConf.CarrierSenseDuringTransmit = DISABLE; + macDefaultConf.ReceiveOwn = ENABLE; + macDefaultConf.LoopbackMode = DISABLE; + macDefaultConf.ChecksumOffload = ENABLE; + macDefaultConf.RetryTransmission = DISABLE; + macDefaultConf.AutomaticPadCRCStrip = DISABLE; + macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10; + macDefaultConf.DeferralCheck = DISABLE; + macDefaultConf.PauseTime = 0x0U; + macDefaultConf.ZeroQuantaPause = DISABLE; + macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + macDefaultConf.ReceiveFlowControl = DISABLE; + macDefaultConf.TransmitFlowControl = DISABLE; + macDefaultConf.Speed = ETH_SPEED_100M; + macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE; + macDefaultConf.UnicastPausePacketDetect = DISABLE; + + /* MAC default configuration */ + ETH_SetMACConfig(heth, &macDefaultConf); + + /*--------------- ETHERNET DMA registers default Configuration --------------*/ + dmaDefaultConf.DropTCPIPChecksumErrorFrame = ENABLE; + dmaDefaultConf.ReceiveStoreForward = ENABLE; + dmaDefaultConf.FlushRxPacket = ENABLE; + dmaDefaultConf.TransmitStoreForward = ENABLE; + dmaDefaultConf.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.ForwardErrorFrames = DISABLE; + dmaDefaultConf.ForwardUndersizedGoodFrames = DISABLE; + dmaDefaultConf.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.SecondFrameOperate = ENABLE; + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.EnhancedDescriptorFormat = ENABLE; + dmaDefaultConf.DescriptorSkipLength = 0x0U; + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; + + /* DMA default configuration */ + ETH_SetDMAConfig(heth, &dmaDefaultConf); +} + +/** + * @brief Configures the selected MAC address. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param MacAddr The MAC address to configure + * This parameter can be one of the following values: + * @arg ETH_MAC_Address0: MAC Address0 + * @arg ETH_MAC_Address1: MAC Address1 + * @arg ETH_MAC_Address2: MAC Address2 + * @arg ETH_MAC_Address3: MAC Address3 + * @param Addr Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg1; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + + /* Calculate the selected MAC address high register */ + tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U]; + /* Load the selected MAC address high register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1; + /* Calculate the selected MAC address low register */ + tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U]; + + /* Load the selected MAC address low register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1; +} + +/** + * @brief Initializes the DMA Tx descriptors. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmatxdesc; + uint32_t i; + + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++) + { + dmatxdesc = heth->Init.TxDesc + i; + + WRITE_REG(dmatxdesc->DESC0, 0x0U); + WRITE_REG(dmatxdesc->DESC1, 0x0U); + WRITE_REG(dmatxdesc->DESC2, 0x0U); + WRITE_REG(dmatxdesc->DESC3, 0x0U); + + WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc); + + /* Set Second Address Chained bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TCH); + + if (i < ((uint32_t)ETH_TX_DESC_CNT - 1U)) + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc + i + 1U)); + } + else + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc)); + } + + /* Set the DMA Tx descriptors checksum insertion */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL); + } + + heth->TxDescList.CurTxDesc = 0; + + /* Set Transmit Descriptor List Address */ + WRITE_REG(heth->Instance->DMATDLAR, (uint32_t) heth->Init.TxDesc); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t i; + + for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++) + { + dmarxdesc = heth->Init.RxDesc + i; + + WRITE_REG(dmarxdesc->DESC0, 0x0U); + WRITE_REG(dmarxdesc->DESC1, 0x0U); + WRITE_REG(dmarxdesc->DESC2, 0x0U); + WRITE_REG(dmarxdesc->DESC3, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr0, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr1, 0x0U); + + /* Set Own bit of the Rx descriptor Status */ + dmarxdesc->DESC0 = ETH_DMARXDESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + dmarxdesc->DESC1 = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE; + + /* Enable Ethernet DMA Rx Descriptor interrupt */ + dmarxdesc->DESC1 &= ~ETH_DMARXDESC_DIC; + + /* Set Rx descritors addresses */ + WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc); + + if (i < ((uint32_t)ETH_RX_DESC_CNT - 1U)) + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc + i + 1U)); + } + else + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc)); + } + } + + WRITE_REG(heth->RxDescList.RxDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxDescCnt, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0U); + WRITE_REG(heth->RxDescList.ItMode, 0U); + + /* Set Receive Descriptor List Address */ + WRITE_REG(heth->Instance->DMARDLAR, (uint32_t) heth->Init.RxDesc); +} + +/** + * @brief Prepare Tx DMA descriptor before transmission. + * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Tx packet configuration + * @param ItMode: Enable or disable Tx EOT interrept + * @retval Status + */ +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t ItMode) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + uint32_t firstdescidx = dmatxdesclist->CurTxDesc; + uint32_t idx; + uint32_t descnbr = 0; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer; + uint32_t bd_count = 0; + uint32_t primask_bit; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + return HAL_ETH_ERROR_BUSY; + } + + + descnbr += 1U; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_DMATXDESC_CIC, pTxConfig->ChecksumCtrl); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_CRC_PAD_DISABLE, pTxConfig->CRCPadCtrl); + } + + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U) + { + /* Set Vlan Type */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_VF); + } + + /* Mark it as First Descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* set OWN bit of FIRST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + + /* only if the packet is split into more than one descriptors > 1 */ + while (txbuffer->next != NULL) + { + /* Clear the LD bit of previous descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* Clear the FD bit of new Descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + descidx = firstdescidx; + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* clear previous desc own bit */ + for (idx = 0; idx < descnbr; idx ++) + { + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + } + + return HAL_ETH_ERROR_BUSY; + } + + descnbr += 1U; + + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + bd_count += 1U; + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set Own bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + } + + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + + /* Mark it as LAST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + /* Save the current packet address to expose it to the application */ + dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress; + + dmatxdesclist->CurTxDesc = descidx; + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1); + + dmatxdesclist->BuffersInUse += bd_count + 1U; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); + + /* Return function status */ + return HAL_ETH_ERROR_NONE; +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->ErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak ErrorCallback */ + heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */ + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; /* Legacy weak RxLinkCallback */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; /* Legacy weak TxFreeCallback */ +#ifdef HAL_ETH_USE_PTP + heth->txPtpCallback = HAL_ETH_TxPtpCallback; /* Legacy weak TxPtpCallback */ +#endif /* HAL_ETH_USE_PTP */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; /* Legacy weak RxAllocateCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ + +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.h new file mode 100644 index 0000000000..5410171dc1 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/F4/stm32f4xx_hal_eth.h @@ -0,0 +1,2019 @@ +/** + ****************************************************************************** + * @file stm32f4xx_hal_eth.h + * @author MCD Application Team + * @brief Header file of ETH HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32F4xx_HAL_ETH_H +#define STM32F4xx_HAL_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal_def.h" + +#if defined(ETH) + +/** @addtogroup STM32F4xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +#ifndef ETH_TX_DESC_CNT +#define ETH_TX_DESC_CNT 4U +#endif /* ETH_TX_DESC_CNT */ + +#ifndef ETH_RX_DESC_CNT +#define ETH_RX_DESC_CNT 4U +#endif /* ETH_RX_DESC_CNT */ + + +/*********************** Descriptors struct def section ************************/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief ETH DMA Descriptor structure definition + */ +typedef struct +{ + __IO uint32_t DESC0; + __IO uint32_t DESC1; + __IO uint32_t DESC2; + __IO uint32_t DESC3; + __IO uint32_t DESC4; + __IO uint32_t DESC5; + __IO uint32_t DESC6; + __IO uint32_t DESC7; + uint32_t BackupAddr0; /* used to store rx buffer 1 address */ + uint32_t BackupAddr1; /* used to store rx buffer 2 address */ +} ETH_DMADescTypeDef; +/** + * + */ + +/** + * @brief ETH Buffers List structure definition + */ +typedef struct __ETH_BufferTypeDef +{ + uint8_t *buffer; /*gState = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_ETH_STATE_RESET; \ + } while(0) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + &= ~(__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT source enabled or disabled. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The ETH DMA IT Source enabled or disabled + */ +#define __HAL_ETH_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMAIER &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The state of ETH DMA IT (SET or RESET) + */ +#define __HAL_ETH_DMA_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMASR &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMASR = (__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMASR &\ + ( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Clears the specified ETHERNET DMA flag. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMASR = ( __FLAG__)) + + + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __INTERRUPT__: specifies the flag to check. @ref ETH_MAC_Interrupts + * @retval The state of ETH MAC IT (SET or RESET). + */ +#define __HAL_ETH_MAC_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MACSR &\ + ( __INTERRUPT__)) == ( __INTERRUPT__)) + +/*!< External interrupt line 19 Connected to the ETH wakeup EXTI Line */ +#define ETH_WAKEUP_EXTI_LINE 0x00080000U + +/** + * @brief Enable the ETH WAKEUP Exti Line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT(__EXTI_LINE__) (EXTI->IMR |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__)) + + +/** + * @brief enable rising edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE(__EXTI_LINE__) (EXTI->FTSR &= ~(__EXTI_LINE__)); \ + (EXTI->RTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR &= ~(__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR |= (__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER |= (__EXTI_LINE__)) + +#define __HAL_ETH_GET_PTP_CONTROL(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->PTPTSCR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +#define __HAL_ETH_SET_PTP_CONTROL(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->PTPTSCR |= (__FLAG__)) + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de initialization functions **********************************/ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth); + +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff); +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(ETH_HandleTypeDef *heth, uint32_t *pErrorCode); +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth); + +#ifdef HAL_ETH_USE_PTP +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset); +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth); +#endif /* HAL_ETH_USE_PTP */ + +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig, uint32_t Timeout); +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfig *pTxConfig); + +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue); +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue); + +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxAllocateCallback(uint8_t **buff); +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length); +void HAL_ETH_TxFreeCallback(uint32_t *buff); +void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp); +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions **********************************************/ +/* MAC & DMA Configuration APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, + uint32_t VLANIdentifier); + +/* MAC L2 Packet Filtering APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable); +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr); + +/* MAC Power Down APIs *****************************************************/ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, + const ETH_PowerDownConfigTypeDef *pPowerDownConfig); +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count); + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F4xx_HAL_ETH_H */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.c b/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.c new file mode 100644 index 0000000000..77d6f84e62 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.c @@ -0,0 +1,3238 @@ +/** + ****************************************************************************** + * @file stm32f7xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and deinitialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The ETH HAL driver can be used as follows: + + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE() + (+++) __HAL_RCC_ETH1TX_CLK_ENABLE() + (+++) __HAL_RCC_ETH1RX_CLK_ENABLE() + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pinout + (##) Configure Ethernet NVIC interrupt (in Interrupt mode) + + (#) Ethernet data reception is asynchronous, so call the following API + to start the listening mode: + (##) HAL_ETH_Start(): + This API starts the MAC and DMA transmission and reception process, + without enabling end of transfer interrupts, in this mode user + has to poll for data reception by calling HAL_ETH_ReadData() + (##) HAL_ETH_Start_IT(): + This API starts the MAC and DMA transmission and reception process, + end of transfer interrupts are enabled in this mode, + HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received + + (#) When data is received user can call the following API to get received data: + (##) HAL_ETH_ReadData(): Read a received packet + + (#) For transmission path, two APIs are available: + (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode + (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode, + HAL_ETH_TxCpltCallback() will be executed when end of transfer occur + + (#) Communication with an external PHY device: + (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY + (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register + + (#) Configure the Ethernet MAC after ETH peripheral initialization + (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef + (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef + + (#) Configure the Ethernet DMA after ETH peripheral initialization + (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef + (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef + + (#) Configure the Ethernet PTP after ETH peripheral initialization + (##) Define HAL_ETH_USE_PTP to use PTP APIs. + (##) HAL_ETH_PTP_GetConfig(): Get PTP actual configuration into ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_SetConfig(): Set PTP configuration based on ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_GetTime(): Get Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_SetTime(): Set Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_AddTimeOffset(): Add Seconds and Nanoseconds offset for the Ethernet PTP registers + (##) HAL_ETH_PTP_InsertTxTimestamp(): Insert Timestamp in transmission + (##) HAL_ETH_PTP_GetTxTimestamp(): Get transmission timestamp + (##) HAL_ETH_PTP_GetRxTimestamp(): Get reception timestamp + + -@- The ARP offload feature is not supported in this driver. + + -@- The PTP offload feature is not supported in this driver. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callbacks RxAllocateCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxPtpCallback(). + + Use function HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + For specific callbacks RxAllocateCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxPtpCallback(). + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ETH_TxCpltCallback(), HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_ETH_RegisterCallback() before calling HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f7xx_hal.h" + +/** @addtogroup STM32F7xx_HAL_Driver + * @{ + */ +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_MACCR_MASK 0xFFFB7F7CU +#define ETH_MACECR_MASK 0x3F077FFFU +#define ETH_MACFFR_MASK 0x800007FFU +#define ETH_MACWTR_MASK 0x0000010FU +#define ETH_MACTFCR_MASK 0xFFFF00F2U +#define ETH_MACRFCR_MASK 0x00000003U +#define ETH_MTLTQOMR_MASK 0x00000072U +#define ETH_MTLRQOMR_MASK 0x0000007BU + +#define ETH_DMAMR_MASK 0x00007802U +#define ETH_DMASBMR_MASK 0x0000D001U +#define ETH_DMACCR_MASK 0x00013FFFU +#define ETH_DMACTCR_MASK 0x003F1010U +#define ETH_DMACRCR_MASK 0x803F0000U +#define ETH_MACPMTCSR_MASK (ETH_MACPMTCSR_PD | ETH_MACPMTCSR_WFE | \ + ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU) + +/* Timeout values */ +#define ETH_SWRESET_TIMEOUT 500U +#define ETH_MDIO_BUS_TIMEOUT 1000U + +#define ETH_DMARXDESC_ERRORS_MASK ((uint32_t)(ETH_DMARXDESC_DBE | ETH_DMARXDESC_RE | \ + ETH_DMARXDESC_OE | ETH_DMARXDESC_RWT |\ + ETH_DMARXDESC_LC | ETH_DMARXDESC_CE |\ + ETH_DMARXDESC_DE | ETH_DMARXDESC_IPV4HCE)) + +#define ETH_MAC_US_TICK 1000000U + +#define ETH_MACTSCR_MASK 0x0087FF2FU + +#define ETH_PTPTSHR_VALUE 0xFFFFFFFFU +#define ETH_PTPTSLR_VALUE 0xBB9ACA00U + +/* Ethernet MACMIIAR register Mask */ +#define ETH_MACMIIAR_CR_MASK 0xFFFFFFE3U + +/* Delay to wait when writing to some Ethernet registers */ +#define ETH_REG_WRITE_DELAY 0x00000001U + +/* ETHERNET MACCR register Mask */ +#define ETH_MACCR_CLEAR_MASK 0xFD20810FU + +/* ETHERNET MACFCR register Mask */ +#define ETH_MACFCR_CLEAR_MASK 0x0000FF41U + +/* ETHERNET DMAOMR register Mask */ +#define ETH_DMAOMR_CLEAR_MASK 0xF8DE3F23U + +/* ETHERNET MAC address offsets */ +#define ETH_MAC_ADDR_HBASE (uint32_t)(ETH_MAC_BASE + 0x40U) /* ETHERNET MAC address high offset */ +#define ETH_MAC_ADDR_LBASE (uint32_t)(ETH_MAC_BASE + 0x44U) /* ETHERNET MAC address low offset */ + +/* ETHERNET DMA Rx descriptors Frame length Shift */ +#define ETH_DMARXDESC_FRAMELENGTHSHIFT 16U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Macros ETH Private Macros + * @{ + */ +/* Helper macros for TX descriptor handling */ +#define INCR_TX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\ + } while (0) + +/* Helper macros for RX descriptor handling */ +#define INCR_RX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\ + } while (0) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf); +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf); +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth); +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth); +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth); +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode); +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth); +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth); +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the ETH peripheral: + + (+) User must Implement HAL_ETH_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO and NVIC ). + + (+) Call the function HAL_ETH_Init() to configure the selected device with + the selected configuration: + (++) MAC address + (++) Media interface (MII or RMII) + (++) Rx DMA Descriptors Tab + (++) Tx DMA Descriptors Tab + (++) Length of Rx Buffers + + (+) Call the function HAL_ETH_DeInit() to restore the default configuration + of the selected ETH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the Ethernet peripheral registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tickstart; + + if (heth == NULL) + { + return HAL_ERROR; + } + if (heth->gState == HAL_ETH_STATE_RESET) + { + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + ETH_InitCallbacksToDefault(heth); + + if (heth->MspInitCallback == NULL) + { + heth->MspInitCallback = HAL_ETH_MspInit; + } + + /* Init the low level hardware */ + heth->MspInitCallback(heth); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + } + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* Select MII or RMII Mode*/ + SYSCFG->PMC &= ~(SYSCFG_PMC_MII_RMII_SEL); + SYSCFG->PMC |= (uint32_t)heth->Init.MediaInterface; + /* Dummy read to sync SYSCFG with ETH */ + (void)SYSCFG->PMC; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + SET_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_SR) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + } + + + /*------------------ MAC, MTL and DMA default Configuration ----------------*/ + ETH_MACDMAConfig(heth); + + + /*------------------ DMA Tx Descriptors Configuration ----------------------*/ + ETH_DMATxDescListInit(heth); + + /*------------------ DMA Rx Descriptors Configuration ----------------------*/ + ETH_DMARxDescListInit(heth); + + /*--------------------- ETHERNET MAC Address Configuration ------------------*/ + ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr); + + /* Disable MMC Interrupts */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM); + + /* Disable Rx MMC Interrupts */ + SET_BIT(heth->Instance->MMCRIMR, ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | \ + ETH_MMCRIMR_RFCEM); + + /* Disable Tx MMC Interrupts */ + SET_BIT(heth->Instance->MMCTIMR, ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | \ + ETH_MMCTIMR_TGFSCM); + + heth->ErrorCode = HAL_ETH_ERROR_NONE; + heth->gState = HAL_ETH_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the ETH peripheral. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + if (heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* DeInit the low level hardware */ + heth->MspDeInitCallback(heth); +#else + + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + + /* Set ETH HAL state to Disabled */ + heth->gState = HAL_ETH_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = pCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = pCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callback is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = HAL_ETH_PMTCallback; + break; + + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief ETH Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the ETH + data transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables Ethernet MAC and DMA reception and transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + heth->gState = HAL_ETH_STATE_STARTED; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* save IT mode to ETH Handle */ + heth->RxDescList.ItMode = 1U; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Enable ETH DMA interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + heth->gState = HAL_ETH_STATE_STARTED; + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t descindex; + uint32_t tmpreg1; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE | + ETH_DMAIER_FBEIE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE)); + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Flush Transmit FIFO */ + ETH_FlushTransmitFIFO(heth); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /* Clear IOC bit to all Rx descriptors */ + for (descindex = 0; descindex < (uint32_t)ETH_RX_DESC_CNT; descindex++) + { + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex]; + SET_BIT(dmarxdesc->DESC1, ETH_DMARXDESC_DIC); + } + + heth->RxDescList.ItMode = 0U; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in polling mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @param Timeout: timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout) +{ + uint32_t tickstart; + ETH_DMADescTypeDef *dmatxdesc; + + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE) + { + /* Set the ETH error code */ + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc]; + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMATPDR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + tickstart = HAL_GetTick(); + + /* Wait for data to be transmitted or timeout occurred */ + while ((dmatxdesc->DESC0 & ETH_DMATXDESC_OWN) != (uint32_t)RESET) + { + if ((heth->Instance->DMASR & ETH_DMASR_FBES) != (uint32_t)RESET) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + heth->DMAErrorCode = heth->Instance->DMASR; + /* Return function status */ + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT; + /* Clear TX descriptor so that we can proceed */ + dmatxdesc->DESC0 = (ETH_DMATXDESC_FS | ETH_DMATXDESC_LS); + return HAL_ERROR; + } + } + } + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in interrupt mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig) +{ + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Save the packet pointer to release. */ + heth->TxDescList.CurrentPacketAddress = (uint32_t *)pTxConfig->pData; + + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE) + { + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET) + { + /* Clear TBUS ETHERNET DMA flag */ + (heth->Instance)->DMASR = ETH_DMASR_TBUS; + /* Resume DMA transmission*/ + (heth->Instance)->DMATPDR = 0U; + } + + return HAL_OK; + + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Read a received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pAppBuff: Pointer to an application buffer to receive the packet. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff) +{ + uint32_t descidx; + ETH_DMADescTypeDef *dmarxdesc; + uint32_t desccnt = 0U; + uint32_t desccntmax; + uint32_t bufflength; + uint8_t rxdataready = 0U; + + if (pAppBuff == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState != HAL_ETH_STATE_STARTED) + { + return HAL_ERROR; + } + + descidx = heth->RxDescList.RxDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccntmax = ETH_RX_DESC_CNT - heth->RxDescList.RxBuildDescCnt; + + /* Check if descriptor is not owned by DMA */ + while ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (desccnt < desccntmax) + && (rxdataready == 0U)) + { + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Get timestamp high */ + heth->RxDescList.TimeStamp.TimeStampHigh = dmarxdesc->DESC7; + /* Get timestamp low */ + heth->RxDescList.TimeStamp.TimeStampLow = dmarxdesc->DESC6; + } + if ((READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) || (heth->RxDescList.pRxStart != NULL)) + { + /* Check first descriptor */ + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_FS) != (uint32_t)RESET) + { + heth->RxDescList.RxDescCnt = 0; + heth->RxDescList.RxDataLength = 0; + } + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + bufflength = ((dmarxdesc->DESC0 & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT); + + /* Check if last descriptor */ + if (READ_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_LS) != (uint32_t)RESET) + { + /* Save Last descriptor index */ + heth->RxDescList.pRxLastRxDesc = dmarxdesc->DESC0; + + /* Packet ready */ + rxdataready = 1; + } + + /* Link data */ + WRITE_REG(dmarxdesc->BackupAddr0, dmarxdesc->DESC2); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Link callback*/ + heth->rxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, bufflength); +#else + /* Link callback */ + HAL_ETH_RxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, (uint16_t) bufflength); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->RxDescList.RxDescCnt++; + heth->RxDescList.RxDataLength += bufflength; + + /* Clear buffer pointer */ + dmarxdesc->BackupAddr0 = 0; + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccnt++; + } + + heth->RxDescList.RxBuildDescCnt += desccnt; + if ((heth->RxDescList.RxBuildDescCnt) != 0U) + { + /* Update Descriptors */ + ETH_UpdateDescriptor(heth); + } + + heth->RxDescList.RxDescIdx = descidx; + + if (rxdataready == 1U) + { + /* Return received packet */ + *pAppBuff = heth->RxDescList.pRxStart; + /* Reset first element */ + heth->RxDescList.pRxStart = NULL; + + return HAL_OK; + } + + /* Packet not ready */ + return HAL_ERROR; +} + +/** + * @brief This function gives back Rx Desc of the last received Packet + * to the DMA, so ETH DMA will be able to use these descriptors + * to receive next Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth) +{ + uint32_t descidx; + uint32_t tailidx; + uint32_t desccount; + ETH_DMADescTypeDef *dmarxdesc; + uint8_t *buff = NULL; + uint8_t allocStatus = 1U; + + descidx = heth->RxDescList.RxBuildDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount = heth->RxDescList.RxBuildDescCnt; + + while ((desccount > 0U) && (allocStatus != 0U)) + { + /* Check if a buffer's attached the descriptor */ + if (READ_REG(dmarxdesc->BackupAddr0) == 0U) + { + /* Get a new buffer. */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Allocate callback*/ + heth->rxAllocateCallback(&buff); +#else + /* Allocate callback */ + HAL_ETH_RxAllocateCallback(&buff); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + if (buff == NULL) + { + allocStatus = 0U; + } + else + { + WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)buff); + WRITE_REG(dmarxdesc->DESC2, (uint32_t)buff); + } + } + + if (allocStatus != 0U) + { + if (heth->RxDescList.ItMode == 0U) + { + WRITE_REG(dmarxdesc->DESC1, heth->Init.RxBuffLen | ETH_DMARXDESC_DIC | ETH_DMARXDESC_RCH); + } + else + { + WRITE_REG(dmarxdesc->DESC1, heth->Init.RxBuffLen | ETH_DMARXDESC_RCH); + } + + SET_BIT(dmarxdesc->DESC0, ETH_DMARXDESC_OWN); + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount--; + } + } + + if (heth->RxDescList.RxBuildDescCnt != desccount) + { + /* Set the tail pointer index */ + tailidx = (descidx + 1U) % ETH_RX_DESC_CNT; + + /* DMB instruction to avoid race condition */ + __DMB(); + + /* Set the Tail pointer address */ + WRITE_REG(heth->Instance->DMARPDR, ((uint32_t)(heth->Init.RxDesc + (tailidx)))); + + heth->RxDescList.RxBuildDescIdx = descidx; + heth->RxDescList.RxBuildDescCnt = desccount; + } +} + +/** + * @brief Register the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxAllocateCallback: pointer to function to alloc buffer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback) +{ + if (rxAllocateCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to allocate buffer */ + heth->rxAllocateCallback = rxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Rx Allocate callback. + * @param buff: pointer to allocated buffer + * @retval None + */ +__weak void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxAllocateCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Link callback. + * @param pStart: pointer to packet start + * @param pEnd: pointer to packet end + * @param buff: pointer to received data + * @param Length: received data length + * @retval None + */ +__weak void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(pStart); + UNUSED(pEnd); + UNUSED(buff); + UNUSED(Length); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxLinkCallback could be implemented in the user file + */ +} + +/** + * @brief Set the Rx link data function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxLinkCallback: pointer to function to link data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback) +{ + if (rxLinkCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to link data */ + heth->rxLinkCallback = rxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx link callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Get the error state of the last received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pErrorCode: pointer to uint32_t to hold the error code + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode) +{ + /* Get error bits. */ + *pErrorCode = READ_BIT(heth->RxDescList.pRxLastRxDesc, ETH_DMARXDESC_ERRORS_MASK); + + return HAL_OK; +} + +/** + * @brief Set the Tx free function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txFreeCallback: pointer to function to release the packet + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback) +{ + if (txFreeCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to free transmmitted packet */ + heth->txFreeCallback = txFreeCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx free callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; + + return HAL_OK; +} + +/** + * @brief Tx Free callback. + * @param buff: pointer to buffer to free + * @retval None + */ +__weak void HAL_ETH_TxFreeCallback(uint32_t *buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxFreeCallback could be implemented in the user file + */ +} + +/** + * @brief Release transmitted Tx packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t numOfBuf = dmatxdesclist->BuffersInUse; + uint32_t idx = dmatxdesclist->releaseIndex; + uint8_t pktTxStatus = 1U; + uint8_t pktInUse; +#ifdef HAL_ETH_USE_PTP + ETH_TimeStampTypeDef *timestamp = &heth->TxTimestamp; +#endif /* HAL_ETH_USE_PTP */ + + /* Loop through buffers in use. */ + while ((numOfBuf != 0U) && (pktTxStatus != 0U)) + { + pktInUse = 1U; + numOfBuf--; + /* If no packet, just examine the next packet. */ + if (dmatxdesclist->PacketAddress[idx] == NULL) + { + /* No packet in use, skip to next. */ + INCR_TX_DESC_INDEX(idx, 1U); + pktInUse = 0U; + } + + if (pktInUse != 0U) + { + /* Determine if the packet has been transmitted. */ + if ((heth->Init.TxDesc[idx].DESC0 & ETH_DMATXDESC_OWN) == 0U) + { +#ifdef HAL_ETH_USE_PTP + if ((heth->Init.TxDesc[idx].DESC3 & ETH_DMATXDESC_LS) + && (heth->Init.TxDesc[idx].DESC3 & ETH_DMATXDESC_TTSS)) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->Init.TxDesc[idx].DESC6; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->Init.TxDesc[idx].DESC7; + } + else + { + timestamp->TimeStampHigh = timestamp->TimeStampLow = UINT32_MAX; + } +#endif /* HAL_ETH_USE_PTP */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered callbacks*/ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + heth->txPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + heth->txFreeCallback(dmatxdesclist->PacketAddress[idx]); +#else + /* Call callbacks */ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + HAL_ETH_TxPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + HAL_ETH_TxFreeCallback(dmatxdesclist->PacketAddress[idx]); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the entry in the in-use array. */ + dmatxdesclist->PacketAddress[idx] = NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + INCR_TX_DESC_INDEX(idx, 1U); + dmatxdesclist->BuffersInUse = numOfBuf; + dmatxdesclist->releaseIndex = idx; + } + else + { + /* Get out of the loop! */ + pktTxStatus = 0U; + } + } + } + return HAL_OK; +} + +#ifdef HAL_ETH_USE_PTP +/** + * @brief Set the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + uint32_t tmpTSCR; + ETH_TimeTypeDef time; + + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + + tmpTSCR = ptpconfig->Timestamp | + ((uint32_t)ptpconfig->TimestampUpdate << ETH_PTPTSCR_TSFCU_Pos) | + ((uint32_t)ptpconfig->TimestampAll << ETH_PTPTSCR_TSSARFE_Pos) | + ((uint32_t)ptpconfig->TimestampRolloverMode << ETH_PTPTSCR_TSSSR_Pos) | + ((uint32_t)ptpconfig->TimestampV2 << ETH_PTPTSCR_TSPTPPSV2E_Pos) | + ((uint32_t)ptpconfig->TimestampEthernet << ETH_PTPTSCR_TSSPTPOEFE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv6 << ETH_PTPTSCR_TSSIPV6FE_Pos) | + ((uint32_t)ptpconfig->TimestampIPv4 << ETH_PTPTSCR_TSSIPV4FE_Pos) | + ((uint32_t)ptpconfig->TimestampEvent << ETH_PTPTSCR_TSSEME_Pos) | + ((uint32_t)ptpconfig->TimestampMaster << ETH_PTPTSCR_TSSMRME_Pos) | + ((uint32_t)ptpconfig->TimestampFilter << ETH_PTPTSCR_TSPFFMAE_Pos) | + ((uint32_t)ptpconfig->TimestampClockType << ETH_PTPTSCR_TSCNT_Pos); + + /* Write to MACTSCR */ + MODIFY_REG(heth->Instance->PTPTSCR, ETH_MACTSCR_MASK, tmpTSCR); + + /* Enable Timestamp */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + WRITE_REG(heth->Instance->PTPSSIR, ptpconfig->TimestampSubsecondInc); + WRITE_REG(heth->Instance->PTPTSAR, ptpconfig->TimestampAddend); + + /* Enable Timestamp */ + if (ptpconfig->TimestampAddendUpdate == ENABLE) + { + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSARU); + while ((heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU) != 0) + { + + } + } + + /* Ptp Init */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSTI); + + /* Set PTP Configuration done */ + heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURED; + + /* Set Seconds */ + time.Seconds = heth->Instance->PTPTSHR; + /* Set NanoSeconds */ + time.NanoSeconds = heth->Instance->PTPTSLR; + + HAL_ETH_PTP_SetTime(heth, &time); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Get the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + ptpconfig->Timestamp = READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSE); + ptpconfig->TimestampUpdate = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSFCU) >> ETH_PTPTSCR_TSFCU_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampAll = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSARFE) >> ETH_PTPTSCR_TSSARFE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampRolloverMode = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSSR) >> ETH_PTPTSCR_TSSSR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampV2 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPTPPSV2E) >> ETH_PTPTSCR_TSPTPPSV2E_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEthernet = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSPTPOEFE) >> ETH_PTPTSCR_TSSPTPOEFE_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampIPv6 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV6FE) >> ETH_PTPTSCR_TSSIPV6FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv4 = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSIPV4FE) >> ETH_PTPTSCR_TSSIPV4FE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEvent = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSEME) >> ETH_PTPTSCR_TSSEME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampMaster = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSSMRME) >> ETH_PTPTSCR_TSSMRME_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampFilter = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSPFFMAE) >> ETH_PTPTSCR_TSPFFMAE_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampClockType = ((READ_BIT(heth->Instance->PTPTSCR, + ETH_PTPTSCR_TSCNT) >> ETH_PTPTSCR_TSCNT_Pos) > 0U) ? ENABLE : DISABLE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to set + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Set Seconds */ + heth->Instance->PTPTSHUR = time->Seconds; + + /* Set NanoSeconds */ + heth->Instance->PTPTSLUR = time->NanoSeconds; + + /* the system time is updated */ + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSTU); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to get + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get Seconds */ + time->Seconds = heth->Instance->PTPTSHR; + /* Get NanoSeconds */ + time->NanoSeconds = heth->Instance->PTPTSLR; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Update time for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timeoffset: pointer to a ETH_PtpUpdateTypeDef structure that contains + * the time update information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + if (ptpoffsettype == HAL_ETH_PTP_NEGATIVE_UPDATE) + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = ETH_PTPTSHR_VALUE - timeoffset->Seconds + 1U; + + if (READ_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSSR) == ETH_PTPTSCR_TSSSR) + { + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = ETH_PTPTSLR_VALUE - timeoffset->NanoSeconds; + } + else + { + heth->Instance->PTPTSLUR = ETH_PTPTSHR_VALUE - timeoffset->NanoSeconds + 1U; + } + } + else + { + /* Set Seconds update */ + heth->Instance->PTPTSHUR = timeoffset->Seconds; + /* Set nanoSeconds update */ + heth->Instance->PTPTSLUR = timeoffset->NanoSeconds; + } + + SET_BIT(heth->Instance->PTPTSCR, ETH_PTPTSCR_TSSTU); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Insert Timestamp in transmission. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Enable Time Stamp transmission */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TTSE); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get transmission timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * transmission timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t idx = dmatxdesclist->releaseIndex; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[idx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = dmatxdesc->DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = dmatxdesc->DESC1; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get receive timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * receive timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->RxDescList.TimeStamp.TimeStampLow; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->RxDescList.TimeStamp.TimeStampHigh; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Register the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txPtpCallback: Function to handle Ptp transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback) +{ + if (txPtpCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + /* Set Function to handle Tx Ptp */ + heth->txPtpCallback = txPtpCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txPtpCallback = HAL_ETH_TxPtpCallback; + + return HAL_OK; +} + +/** + * @brief Tx Ptp callback. + * @param buff: pointer to application buffer + * @param timestamp: pointer to ETH_TimeStampTypeDef structure that contains + * transmission timestamp + * @retval None + */ +__weak void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxPtpCallback could be implemented in the user file + */ +} +#endif /* HAL_ETH_USE_PTP */ + +/** + * @brief This function handles ETH interrupt request. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + uint32_t mac_flag = READ_REG(heth->Instance->MACSR); + uint32_t dma_flag = READ_REG(heth->Instance->DMASR); + uint32_t dma_itsource = READ_REG(heth->Instance->DMAIER); + uint32_t exti_flag = READ_REG(EXTI->PR); + + /* Packet received */ + if (((dma_flag & ETH_DMASR_RS) != 0U) && ((dma_itsource & ETH_DMAIER_RIE) != 0U)) + { + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_RS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* Packet transmitted */ + if (((dma_flag & ETH_DMASR_TS) != 0U) && ((dma_itsource & ETH_DMAIER_TIE) != 0U)) + { + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMASR_TS | ETH_DMASR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Transmit complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* ETH DMA Error */ + if (((dma_flag & ETH_DMASR_AIS) != 0U) && ((dma_itsource & ETH_DMAIER_AISE) != 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + /* if fatal bus error occurred */ + if ((dma_flag & ETH_DMASR_FBES) != 0U) + { + /* Get DMA error code */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_FBES | ETH_DMASR_TPS | ETH_DMASR_RPS)); + + /* Disable all interrupts */ + __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMAIER_NISE | ETH_DMAIER_AISE); + + /* Set HAL state to ERROR */ + heth->gState = HAL_ETH_STATE_ERROR; + } + else + { + /* Get DMA error status */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMASR, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + + /* Clear the interrupt summary flag */ + __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMASR_ETS | ETH_DMASR_RWTS | + ETH_DMASR_RBUS | ETH_DMASR_AIS)); + } +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet DMA Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + + /* ETH PMT IT */ + if ((mac_flag & ETH_MAC_PMT_IT) != 0U) + { + /* Get MAC Wake-up source and clear the status register pending bit */ + heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPMTCSR, (ETH_MACPMTCSR_WFR | ETH_MACPMTCSR_MPR)); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered PMT callback*/ + heth->PMTCallback(heth); +#else + /* Ethernet PMT callback */ + HAL_ETH_PMTCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACWakeUpEvent = (uint32_t)(0x0U); + } + + + /* check ETH WAKEUP exti flag */ + if ((exti_flag & ETH_WAKEUP_EXTI_LINE) != 0U) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet Power Management module IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_PMTCallback could be implemented in the user file + */ +} + + +/** + * @brief ETH WAKEUP interrupt callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_WakeUpCallback could be implemented in the user file + */ +} + +/** + * @brief Read a PHY register + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param pRegValue: parameter to hold read value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII address register value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_READ_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + /* Get MACMIIDR value */ + *pRegValue = (uint16_t)(heth->Instance->MACMIIDR); + + return HAL_OK; +} + +/** + * @brief Writes to a PHY register. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param RegValue: the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue) +{ + uint32_t tmpreg1; + uint32_t tickstart; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg1 = heth->Instance->MACMIIAR; + + /* Keep only the CSR Clock Range CR[2:0] bits value */ + tmpreg1 &= ~ETH_MACMIIAR_CR_MASK; + + /* Prepare the MII register address value */ + tmpreg1 |= ((PHYAddr << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */ + tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */ + tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */ + tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */ + + /* Give the value to the MII data register */ + heth->Instance->MACMIIDR = (uint16_t)RegValue; + + /* Write the result value into the MII Address register */ + heth->Instance->MACMIIAR = tmpreg1; + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Check for the Busy flag */ + while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB) + { + /* Check for the Timeout */ + if ((HAL_GetTick() - tickstart) > PHY_WRITE_TO) + { + return HAL_ERROR; + } + + tmpreg1 = heth->Instance->MACMIIAR; + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief ETH control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the ETH + peripheral. + +@endverbatim + * @{ + */ +/** + * @brief Get the configuration of the MAC and MTL subsystems. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold + * the configuration of the MAC. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + /* Get MAC parameters */ + macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL); + macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_RD) >> 9) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CSD) >> 16) > 0U) + ? ENABLE : DISABLE; + macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ROD) >> 13) == 0U) ? ENABLE : DISABLE; + macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE; + macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM); + macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES); + macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >> 22) == 0U) ? ENABLE : DISABLE; + macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >> 23) == 0U) ? ENABLE : DISABLE; + macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_APCS) >> 7) > 0U) ? ENABLE : DISABLE; + macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IFG); + macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPCO) >> 10U) > 0U) ? ENABLE : DISABLE; + macconf->CRCStripTypePacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CSTF) >> 25U) > 0U) ? ENABLE : DISABLE; + + macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_TFCE) >> 1) > 0U) ? ENABLE : DISABLE; + macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_ZQPD) >> 7) == 0U) ? ENABLE : DISABLE; + macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PLT); + macconf->PauseTime = (READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_PT) >> 16); + macconf->ReceiveFlowControl = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_RFCE) >> 2U) > 0U) ? ENABLE : DISABLE; + macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACFCR, ETH_MACFCR_UPFD) >> 3U) > 0U) + ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Get the configuration of the DMA. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMABMR, + (ETH_DMAARBITRATION_RXPRIORTX | ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1)); + dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_AAB) >> 25U) > 0U) ? ENABLE : DISABLE; + dmaconf->BurstMode = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_FB | ETH_DMABMR_MB); + dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_RDP); + dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_PBL); + dmaconf->EnhancedDescriptorFormat = ((READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_EDE) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->DescriptorSkipLength = READ_BIT(heth->Instance->DMABMR, ETH_DMABMR_DSL) >> 2; + + dmaconf->DropTCPIPChecksumErrorFrame = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_DTCEFD) >> 26) > 0U) ? DISABLE : ENABLE; + dmaconf->ReceiveStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RSF) >> 25) > 0U) ? ENABLE : DISABLE; + dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FTF) >> 20) > 0U) ? DISABLE : ENABLE; + dmaconf->TransmitStoreForward = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TSF) >> 21) > 0U) ? ENABLE : DISABLE; + dmaconf->TransmitThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_TTC); + dmaconf->ForwardErrorFrames = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_FEF) >> 7) > 0U) ? ENABLE : DISABLE; + dmaconf->ForwardUndersizedGoodFrames = ((READ_BIT(heth->Instance->DMAOMR, + ETH_DMAOMR_FUGF) >> 6) > 0U) ? ENABLE : DISABLE; + dmaconf->ReceiveThresholdControl = READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_RTC); + dmaconf->SecondFrameOperate = ((READ_BIT(heth->Instance->DMAOMR, ETH_DMAOMR_OSF) >> 2) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the MAC configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains + * the configuration of the MAC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetMACConfig(heth, macconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Set the ETH DMA configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetDMAConfig(heth, dmaconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configures the Clock range of ETH MDIO interface. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth) +{ + uint32_t hclk; + uint32_t tmpreg; + + /* Get the ETHERNET MACMIIAR value */ + tmpreg = (heth->Instance)->MACMIIAR; + /* Clear CSR Clock Range CR[2:0] bits */ + tmpreg &= ETH_MACMIIAR_CR_MASK; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if (hclk < 35000000U) + { + /* CSR Clock Range between 0-35 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div16; + } + else if (hclk < 60000000U) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div26; + } + else if (hclk < 100000000U) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div42; + } + else if (hclk < 150000000U) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div62; + } + else /* (hclk >= 150000000) */ + { + /* CSR Clock >= 150 MHz */ + tmpreg |= (uint32_t)ETH_MACMIIAR_CR_Div102; + } + + /* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */ + (heth->Instance)->MACMIIAR = (uint32_t)tmpreg; +} + +/** + * @brief Set the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + uint32_t filterconfig; + uint32_t tmpreg1; + + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode | + ((uint32_t)pFilterConfig->HashUnicast << 1) | + ((uint32_t)pFilterConfig->HashMulticast << 2) | + ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) | + ((uint32_t)pFilterConfig->PassAllMulticast << 4) | + ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) | + ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) | + ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) | + ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) | + ((uint32_t)pFilterConfig->ReceiveAllMode << 31) | + pFilterConfig->ControlPacketsFilter); + + MODIFY_REG(heth->Instance->MACFFR, ETH_MACFFR_MASK, filterconfig); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFFR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFFR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Get the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PM)) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HU) >> 1) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HM) >> 2) > 0U) ? ENABLE : DISABLE; + pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE; + pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PAM) >> 4) > 0U) ? ENABLE : DISABLE; + pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_BFD) >> 5) == 0U) ? ENABLE : DISABLE; + pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_PCF); + pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACFFR, + ETH_MACFFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE; + pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_HPF) >> 10) > 0U) + ? ENABLE : DISABLE; + pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACFFR, ETH_MACFFR_RA) >> 31) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the source MAC Address to be matched. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param AddrNbr: The MAC address to configure + * This parameter must be a value of the following: + * ETH_MAC_ADDRESS1 + * ETH_MAC_ADDRESS2 + * ETH_MAC_ADDRESS3 + * @param pMACAddr: Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr) +{ + uint32_t macaddrlr; + uint32_t macaddrhr; + + if (pMACAddr == NULL) + { + return HAL_ERROR; + } + + /* Get mac addr high reg offset */ + macaddrhr = ((uint32_t) &(heth->Instance->MACA0HR) + AddrNbr); + /* Get mac addr low reg offset */ + macaddrlr = ((uint32_t) &(heth->Instance->MACA0LR) + AddrNbr); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) | + ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= (ETH_MACA1HR_AE | ETH_MACA1HR_SA); + + return HAL_OK; +} + +/** + * @brief Set the ETH Hash Table Value. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pHashTable: pointer to a table of two 32 bit values, that contains + * the 64 bits of the hash table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable) +{ + uint32_t tmpreg1; + if (pHashTable == NULL) + { + return HAL_ERROR; + } + + heth->Instance->MACHTHR = pHashTable[0]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTHR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTHR = tmpreg1; + + heth->Instance->MACHTLR = pHashTable[1]; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACHTLR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACHTLR = tmpreg1; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Identifier for Rx packets + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ComparisonBits: 12 or 16 bit comparison mode + must be a value of @ref ETH_VLAN_Tag_Comparison + * @param VLANIdentifier: VLAN Identifier value + * @retval None + */ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier) +{ + uint32_t tmpreg1; + MODIFY_REG(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTI, VLANIdentifier); + if (ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT) + { + CLEAR_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + else + { + SET_BIT(heth->Instance->MACVLANTR, ETH_MACVLANTR_VLANTC); + } + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACVLANTR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACVLANTR = tmpreg1; +} + +/** + * @brief Enters the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure + * that contains the Power Down configuration + * @retval None. + */ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, const ETH_PowerDownConfigTypeDef *pPowerDownConfig) +{ + uint32_t powerdownconfig; + + powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << ETH_MACPMTCSR_MPE_Pos) | + ((uint32_t)pPowerDownConfig->WakeUpPacket << ETH_MACPMTCSR_WFE_Pos) | + ((uint32_t)pPowerDownConfig->GlobalUnicast << ETH_MACPMTCSR_GU_Pos) | + ETH_MACPMTCSR_PD); + + MODIFY_REG(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_MASK, powerdownconfig); +} + +/** + * @brief Exits from the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth) +{ + uint32_t tmpreg1; + + /* clear wake up sources */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFE | ETH_MACPMTCSR_MPE | ETH_MACPMTCSR_GU); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + + if (READ_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD) != 0U) + { + /* Exit power down mode */ + CLEAR_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_PD); + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACPMTCSR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACPMTCSR = tmpreg1; + } + + /* Disable PMT interrupt */ + SET_BIT(heth->Instance->MACIMR, ETH_MACIMR_PMTIM); +} + +/** + * @brief Set the WakeUp filter. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilter: pointer to filter registers values + * @param Count: number of filter registers, must be from 1 to 8. + * @retval None. + */ +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count) +{ + uint32_t regindex; + + if (pFilter == NULL) + { + return HAL_ERROR; + } + + /* Reset Filter Pointer */ + SET_BIT(heth->Instance->MACPMTCSR, ETH_MACPMTCSR_WFFRPR); + + /* Wake up packet filter config */ + for (regindex = 0; regindex < Count; regindex++) + { + /* Write filter regs */ + WRITE_REG(heth->Instance->MACRWUFFR, pFilter[regindex]); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief ETH State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + ETH communication process, return Peripheral Errors occurred during communication + process + + +@endverbatim + * @{ + */ + +/** + * @brief Returns the ETH state. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth) +{ + return heth->gState; +} + +/** + * @brief Returns the ETH error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH Error Code + */ +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth) +{ + return heth->ErrorCode; +} + +/** + * @brief Returns the ETH DMA error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH DMA Error Code + */ +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth) +{ + return heth->DMAErrorCode; +} + +/** + * @brief Returns the ETH MAC error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC Error Code + */ +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth) +{ + return heth->MACErrorCode; +} + +/** + * @brief Returns the ETH MAC WakeUp event source + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event source + */ +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth) +{ + return heth->MACWakeUpEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions ETH Private Functions + * @{ + */ + +/** + * @brief Clears the ETHERNET transmit FIFO. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth) +{ + __IO uint32_t tmpreg = 0; + + /* Set the Flush Transmit FIFO bit */ + (heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg; +} + +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf) +{ + uint32_t tmpreg1; + + /*------------------------ ETHERNET MACCR Configuration --------------------*/ + /* Get the ETHERNET MACCR value */ + tmpreg1 = (heth->Instance)->MACCR; + /* Clear CSTF, WD, PCE, PS, TE and RE bits */ + tmpreg1 &= ETH_MACCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)macconf->CRCStripTypePacket << 25U) | + ((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 23U) | + ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 22U) | + (uint32_t)macconf->InterPacketGapVal | + ((uint32_t)macconf->CarrierSenseDuringTransmit << 16U) | + macconf->Speed | + ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 13U) | + ((uint32_t)macconf->LoopbackMode << 12U) | + macconf->DuplexMode | + ((uint32_t)macconf->ChecksumOffload << 10U) | + ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 9U) | + ((uint32_t)macconf->AutomaticPadCRCStrip << 7U) | + macconf->BackOffLimit | + ((uint32_t)macconf->DeferralCheck << 4U)); + + /* Write to ETHERNET MACCR */ + (heth->Instance)->MACCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACCR = tmpreg1; + + /*----------------------- ETHERNET MACFCR Configuration --------------------*/ + + /* Get the ETHERNET MACFCR value */ + tmpreg1 = (heth->Instance)->MACFCR; + /* Clear xx bits */ + tmpreg1 &= ETH_MACFCR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) | + ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U) << 7U) | + macconf->PauseLowThreshold | + ((uint32_t)((macconf->UnicastPausePacketDetect == ENABLE) ? 1U : 0U) << 3U) | + ((uint32_t)((macconf->ReceiveFlowControl == ENABLE) ? 1U : 0U) << 2U) | + ((uint32_t)((macconf->TransmitFlowControl == ENABLE) ? 1U : 0U) << 1U)); + + /* Write to ETHERNET MACFCR */ + (heth->Instance)->MACFCR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account : + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->MACFCR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->MACFCR = tmpreg1; +} + +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf) +{ + uint32_t tmpreg1; + + /*----------------------- ETHERNET DMAOMR Configuration --------------------*/ + /* Get the ETHERNET DMAOMR value */ + tmpreg1 = (heth->Instance)->DMAOMR; + /* Clear xx bits */ + tmpreg1 &= ETH_DMAOMR_CLEAR_MASK; + + tmpreg1 |= (uint32_t)(((uint32_t)((dmaconf->DropTCPIPChecksumErrorFrame == DISABLE) ? 1U : 0U) << 26U) | + ((uint32_t)dmaconf->ReceiveStoreForward << 25U) | + ((uint32_t)((dmaconf->FlushRxPacket == DISABLE) ? 1U : 0U) << 20U) | + ((uint32_t)dmaconf->TransmitStoreForward << 21U) | + dmaconf->TransmitThresholdControl | + ((uint32_t)dmaconf->ForwardErrorFrames << 7U) | + ((uint32_t)dmaconf->ForwardUndersizedGoodFrames << 6U) | + dmaconf->ReceiveThresholdControl | + ((uint32_t)dmaconf->SecondFrameOperate << 2U)); + + /* Write to ETHERNET DMAOMR */ + (heth->Instance)->DMAOMR = (uint32_t)tmpreg1; + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMAOMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMAOMR = tmpreg1; + + /*----------------------- ETHERNET DMABMR Configuration --------------------*/ + (heth->Instance)->DMABMR = (uint32_t)(((uint32_t)dmaconf->AddressAlignedBeats << 25U) | + dmaconf->BurstMode | + dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or + Rx it is applied for the other */ + dmaconf->TxDMABurstLength | + ((uint32_t)dmaconf->EnhancedDescriptorFormat << 7U) | + (dmaconf->DescriptorSkipLength << 2U) | + dmaconf->DMAArbitration | + ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */ + + /* Wait until the write operation will be taken into account: + at least four TX_CLK/RX_CLK clock cycles */ + tmpreg1 = (heth->Instance)->DMABMR; + HAL_Delay(ETH_REG_WRITE_DELAY); + (heth->Instance)->DMABMR = tmpreg1; +} + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth) +{ + ETH_MACConfigTypeDef macDefaultConf; + ETH_DMAConfigTypeDef dmaDefaultConf; + + /*--------------- ETHERNET MAC registers default Configuration --------------*/ + macDefaultConf.Watchdog = ENABLE; + macDefaultConf.Jabber = ENABLE; + macDefaultConf.InterPacketGapVal = ETH_INTERFRAMEGAP_96BIT; + macDefaultConf.CarrierSenseDuringTransmit = DISABLE; + macDefaultConf.ReceiveOwn = ENABLE; + macDefaultConf.LoopbackMode = DISABLE; + macDefaultConf.CRCStripTypePacket = ENABLE; + macDefaultConf.ChecksumOffload = ENABLE; + macDefaultConf.RetryTransmission = DISABLE; + macDefaultConf.AutomaticPadCRCStrip = DISABLE; + macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10; + macDefaultConf.DeferralCheck = DISABLE; + macDefaultConf.PauseTime = 0x0U; + macDefaultConf.ZeroQuantaPause = DISABLE; + macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4; + macDefaultConf.ReceiveFlowControl = DISABLE; + macDefaultConf.TransmitFlowControl = DISABLE; + macDefaultConf.Speed = ETH_SPEED_100M; + macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE; + macDefaultConf.UnicastPausePacketDetect = DISABLE; + + /* MAC default configuration */ + ETH_SetMACConfig(heth, &macDefaultConf); + + /*--------------- ETHERNET DMA registers default Configuration --------------*/ + dmaDefaultConf.DropTCPIPChecksumErrorFrame = ENABLE; + dmaDefaultConf.ReceiveStoreForward = ENABLE; + dmaDefaultConf.FlushRxPacket = ENABLE; + dmaDefaultConf.TransmitStoreForward = ENABLE; + dmaDefaultConf.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.ForwardErrorFrames = DISABLE; + dmaDefaultConf.ForwardUndersizedGoodFrames = DISABLE; + dmaDefaultConf.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES; + dmaDefaultConf.SecondFrameOperate = ENABLE; + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.EnhancedDescriptorFormat = ENABLE; + dmaDefaultConf.DescriptorSkipLength = 0x0U; + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1; + + /* DMA default configuration */ + ETH_SetDMAConfig(heth, &dmaDefaultConf); +} +/** + * @brief Configures the selected MAC address. + * @param heth pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param MacAddr The MAC address to configure + * This parameter can be one of the following values: + * @arg ETH_MAC_Address0: MAC Address0 + * @arg ETH_MAC_Address1: MAC Address1 + * @arg ETH_MAC_Address2: MAC Address2 + * @arg ETH_MAC_Address3: MAC Address3 + * @param Addr Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr) +{ + uint32_t tmpreg1; + + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + + /* Calculate the selected MAC address high register */ + tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U]; + /* Load the selected MAC address high register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1; + /* Calculate the selected MAC address low register */ + tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U]; + + /* Load the selected MAC address low register */ + (*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1; +} + +/** + * @brief Initializes the DMA Tx descriptors. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmatxdesc; + uint32_t i; + + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++) + { + dmatxdesc = heth->Init.TxDesc + i; + + WRITE_REG(dmatxdesc->DESC0, 0x0U); + WRITE_REG(dmatxdesc->DESC1, 0x0U); + WRITE_REG(dmatxdesc->DESC2, 0x0U); + WRITE_REG(dmatxdesc->DESC3, 0x0U); + + WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc); + + /* Set Second Address Chained bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_TCH); + + if (i < ((uint32_t)ETH_TX_DESC_CNT - 1U)) + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc + i + 1U)); + } + else + { + WRITE_REG(dmatxdesc->DESC3, (uint32_t)(heth->Init.TxDesc)); + } + + /* Set the DMA Tx descriptors checksum insertion */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL); + } + + heth->TxDescList.CurTxDesc = 0; + + /* Set Transmit Descriptor List Address */ + WRITE_REG(heth->Instance->DMATDLAR, (uint32_t) heth->Init.TxDesc); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t i; + + for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++) + { + dmarxdesc = heth->Init.RxDesc + i; + + WRITE_REG(dmarxdesc->DESC0, 0x0U); + WRITE_REG(dmarxdesc->DESC1, 0x0U); + WRITE_REG(dmarxdesc->DESC2, 0x0U); + WRITE_REG(dmarxdesc->DESC3, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr0, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr1, 0x0U); + + /* Set Own bit of the Rx descriptor Status */ + dmarxdesc->DESC0 = ETH_DMARXDESC_OWN; + + /* Set Buffer1 size and Second Address Chained bit */ + dmarxdesc->DESC1 = heth->Init.RxBuffLen | ETH_DMARXDESC_RCH; + + /* Enable Ethernet DMA Rx Descriptor interrupt */ + dmarxdesc->DESC1 &= ~ETH_DMARXDESC_DIC; + /* Set Rx descritors addresses */ + WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc); + + if (i < ((uint32_t)ETH_RX_DESC_CNT - 1U)) + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc + i + 1U)); + } + else + { + WRITE_REG(dmarxdesc->DESC3, (uint32_t)(heth->Init.RxDesc)); + } + } + + WRITE_REG(heth->RxDescList.RxDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxDescCnt, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0U); + WRITE_REG(heth->RxDescList.ItMode, 0U); + + /* Set Receive Descriptor List Address */ + WRITE_REG(heth->Instance->DMARDLAR, (uint32_t) heth->Init.RxDesc); +} + +/** + * @brief Prepare Tx DMA descriptor before transmission. + * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Tx packet configuration + * @param ItMode: Enable or disable Tx EOT interrept + * @retval Status + */ +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + uint32_t firstdescidx = dmatxdesclist->CurTxDesc; + uint32_t idx; + uint32_t descnbr = 0; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer; + uint32_t bd_count = 0; + uint32_t primask_bit; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + return HAL_ETH_ERROR_BUSY; + } + + + descnbr += 1U; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_DMATXDESC_CIC, pTxConfig->ChecksumCtrl); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != 0U) + { + MODIFY_REG(dmatxdesc->DESC0, ETH_CRC_PAD_DISABLE, pTxConfig->CRCPadCtrl); + } + + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != 0U) + { + /* Set Vlan Type */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_VF); + } + + /* Mark it as First Descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + /* only if the packet is split into more than one descriptors > 1 */ + while (txbuffer->next != NULL) + { + /* Clear the LD bit of previous descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN) == ETH_DMATXDESC_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + descidx = firstdescidx; + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* clear previous desc own bit */ + for (idx = 0; idx < descnbr; idx ++) + { + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + } + + return HAL_ETH_ERROR_BUSY; + } + + /* Clear the FD bit of new Descriptor */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_FS); + + descnbr += 1U; + + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC2, (uint32_t)txbuffer->buffer); + + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC1, ETH_DMATXDESC_TBS1, txbuffer->len); + + bd_count += 1U; + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set Own bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + } + + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_IC); + } + + /* Mark it as LAST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_LS); + + /* Get address of first descriptor */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[firstdescidx]; + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* set OWN bit of FIRST descriptor */ + SET_BIT(dmatxdesc->DESC0, ETH_DMATXDESC_OWN); + /* Save the current packet address to expose it to the application */ + dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress; + + dmatxdesclist->CurTxDesc = descidx; + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1); + + dmatxdesclist->BuffersInUse += bd_count + 1U; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); + + /* Return function status */ + return HAL_ETH_ERROR_NONE; +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->ErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak ErrorCallback */ + heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */ + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; /* Legacy weak RxLinkCallback */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; /* Legacy weak TxFreeCallback */ +#ifdef HAL_ETH_USE_PTP + heth->txPtpCallback = HAL_ETH_TxPtpCallback; /* Legacy weak TxPtpCallback */ +#endif /* HAL_ETH_USE_PTP */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; /* Legacy weak RxAllocateCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ + +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.h new file mode 100644 index 0000000000..3c7035d82e --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/F7/stm32f7xx_hal_eth.h @@ -0,0 +1,2017 @@ +/** + ****************************************************************************** + * @file stm32f7xx_hal_eth.h + * @author MCD Application Team + * @brief Header file of ETH HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32F7xx_HAL_ETH_H +#define STM32F7xx_HAL_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f7xx_hal_def.h" + +#if defined(ETH) + +/** @addtogroup STM32F7xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +#ifndef ETH_TX_DESC_CNT +#define ETH_TX_DESC_CNT 4U +#endif /* ETH_TX_DESC_CNT */ + +#ifndef ETH_RX_DESC_CNT +#define ETH_RX_DESC_CNT 4U +#endif /* ETH_RX_DESC_CNT */ + + +/*********************** Descriptors struct def section ************************/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief ETH DMA Descriptor structure definition + */ +typedef struct +{ + __IO uint32_t DESC0; + __IO uint32_t DESC1; + __IO uint32_t DESC2; + __IO uint32_t DESC3; + __IO uint32_t DESC4; + __IO uint32_t DESC5; + __IO uint32_t DESC6; + __IO uint32_t DESC7; + uint32_t BackupAddr0; /* used to store rx buffer 1 address */ + uint32_t BackupAddr1; /* used to store rx buffer 2 address */ +} ETH_DMADescTypeDef; +/** + * + */ + +/** + * @brief ETH Buffers List structure definition + */ +typedef struct __ETH_BufferTypeDef +{ + uint8_t *buffer; /*gState = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_ETH_STATE_RESET; \ + } while(0) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMAIER \ + &= ~(__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT source enabled or disabled. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The ETH DMA IT Source enabled or disabled + */ +#define __HAL_ETH_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMAIER &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The state of ETH DMA IT (SET or RESET) + */ +#define __HAL_ETH_DMA_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->DMASR &\ + (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMASR = (__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMASR &\ + ( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Clears the specified ETHERNET DMA flag. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMASR = ( __FLAG__)) + + + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __INTERRUPT__: specifies the flag to check. @ref ETH_MAC_Interrupts + * @retval The state of ETH MAC IT (SET or RESET). + */ +#define __HAL_ETH_MAC_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MACSR &\ + ( __INTERRUPT__)) == ( __INTERRUPT__)) + +/*!< External interrupt line 19 Connected to the ETH wakeup EXTI Line */ +#define ETH_WAKEUP_EXTI_LINE 0x00080000U + +/** + * @brief Enable the ETH WAKEUP Exti Line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT(__EXTI_LINE__) (EXTI->IMR |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->PR & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->PR = (__EXTI_LINE__)) + +/** + * @brief enable rising edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE(__EXTI_LINE__) (EXTI->FTSR &= ~(__EXTI_LINE__)); \ + (EXTI->RTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR &= ~(__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR |= (__EXTI_LINE__));\ + (EXTI->FTSR |= (__EXTI_LINE__)) + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER |= (__EXTI_LINE__)) + +#define __HAL_ETH_GET_PTP_CONTROL(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->PTPTSCR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) + +#define __HAL_ETH_SET_PTP_CONTROL(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->PTPTSCR |= (__FLAG__)) + +/** + * @} + */ + + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de initialization functions **********************************/ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth); + +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff); +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode); +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth); + +#ifdef HAL_ETH_USE_PTP +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset); +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth); +#endif /* HAL_ETH_USE_PTP */ + +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout); +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig); + +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue); +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue); + +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxAllocateCallback(uint8_t **buff); +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length); +void HAL_ETH_TxFreeCallback(uint32_t *buff); +void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp); +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions **********************************************/ +/* MAC & DMA Configuration APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, + uint32_t VLANIdentifier); + +/* MAC L2 Packet Filtering APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable); +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr); + +/* MAC Power Down APIs *****************************************************/ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, + const ETH_PowerDownConfigTypeDef *pPowerDownConfig); +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count); + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32F7xx_HAL_ETH_H */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.c b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.c new file mode 100644 index 0000000000..d04ecc6f43 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.c @@ -0,0 +1,3341 @@ +/** + ****************************************************************************** + * @file stm32h5xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and deinitialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The ETH HAL driver can be used as follows: + + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE() + (+++) __HAL_RCC_ETH1TX_CLK_ENABLE() + (+++) __HAL_RCC_ETH1RX_CLK_ENABLE() + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pinout + (##) Configure Ethernet NVIC interrupt (in Interrupt mode) + + (#) Ethernet data reception is asynchronous, so call the following API + to start the listening mode: + (##) HAL_ETH_Start(): + This API starts the MAC and DMA transmission and reception process, + without enabling end of transfer interrupts, in this mode user + has to poll for data reception by calling HAL_ETH_ReadData() + (##) HAL_ETH_Start_IT(): + This API starts the MAC and DMA transmission and reception process, + end of transfer interrupts are enabled in this mode, + HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received + + (#) When data is received user can call the following API to get received data: + (##) HAL_ETH_ReadData(): Read a received packet + + (#) For transmission path, two APIs are available: + (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode + (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode, + HAL_ETH_TxCpltCallback() will be executed when end of transfer occur + + (#) Communication with an external PHY device: + (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY + (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register + + (#) Configure the Ethernet MAC after ETH peripheral initialization + (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef + (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef + + (#) Configure the Ethernet DMA after ETH peripheral initialization + (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef + (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef + + (#) Configure the Ethernet PTP after ETH peripheral initialization + (##) Define HAL_ETH_USE_PTP to use PTP APIs. + (##) HAL_ETH_PTP_GetConfig(): Get PTP actual configuration into ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_SetConfig(): Set PTP configuration based on ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_GetTime(): Get Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_SetTime(): Set Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_AddTimeOffset(): Add Seconds and Nanoseconds offset for the Ethernet PTP registers + (##) HAL_ETH_PTP_InsertTxTimestamp(): Insert Timestamp in transmission + (##) HAL_ETH_PTP_GetTxTimestamp(): Get transmission timestamp + (##) HAL_ETH_PTP_GetRxTimestamp(): Get reception timestamp + + -@- The ARP offload feature is not supported in this driver. + + -@- The PTP offload feature is not supported in this driver. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callbacks RxAllocateCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxPtpCallback(). + + Use function HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + For specific callbacks RxAllocateCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxPtpCallback(). + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ETH_TxCpltCallback(), HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_ETH_RegisterCallback() before calling HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h5xx_hal.h" + +/** @addtogroup STM32H5xx_HAL_Driver + * @{ + */ +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_MACCR_MASK 0xFFFB7F7CU +#define ETH_MACECR_MASK 0x3F077FFFU +#define ETH_MACPFR_MASK 0x800007FFU +#define ETH_MACWTR_MASK 0x0000010FU +#define ETH_MACTFCR_MASK 0xFFFF00F2U +#define ETH_MACRFCR_MASK 0x00000003U +#define ETH_MTLTQOMR_MASK 0x00000072U +#define ETH_MTLRQOMR_MASK 0x0000007BU + +#define ETH_DMAMR_MASK 0x00007802U +#define ETH_DMASBMR_MASK 0x0000D001U +#define ETH_DMACCR_MASK 0x00013FFFU +#define ETH_DMACTCR_MASK 0x003F1010U +#define ETH_DMACRCR_MASK 0x803F0000U +#define ETH_MACPCSR_MASK (ETH_MACPCSR_PWRDWN | ETH_MACPCSR_RWKPKTEN | \ + ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | \ + ETH_MACPCSR_RWKPFE) + +/* Timeout values */ +#define ETH_DMARXNDESCWBF_ERRORS_MASK ((uint32_t)(ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | \ + ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT |\ + ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE)) + +#define ETH_MACTSCR_MASK 0x0087FF2FU + +#define ETH_MACSTSUR_VALUE 0xFFFFFFFFU +#define ETH_MACSTNUR_VALUE 0xBB9ACA00U +#define ETH_SEGMENT_SIZE_DEFAULT 0x218U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Macros ETH Private Macros + * @{ + */ +/* Helper macros for TX descriptor handling */ +#define INCR_TX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\ + } while (0) + +/* Helper macros for RX descriptor handling */ +#define INCR_RX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\ + } while (0) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf); +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf); +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth); +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth); +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth); +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode); +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the ETH peripheral: + + (+) User must Implement HAL_ETH_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO and NVIC ). + + (+) Call the function HAL_ETH_Init() to configure the selected device with + the selected configuration: + (++) MAC address + (++) Media interface (MII or RMII) + (++) Rx DMA Descriptors Tab + (++) Tx DMA Descriptors Tab + (++) Length of Rx Buffers + + (+) Call the function HAL_ETH_DeInit() to restore the default configuration + of the selected ETH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the Ethernet peripheral registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tickstart; + + if (heth == NULL) + { + return HAL_ERROR; + } + if (heth->gState == HAL_ETH_STATE_RESET) + { + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + ETH_InitCallbacksToDefault(heth); + + if (heth->MspInitCallback == NULL) + { + heth->MspInitCallback = HAL_ETH_MspInit; + } + + /* Init the low level hardware */ + heth->MspInitCallback(heth); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + } + + __HAL_RCC_SBS_CLK_ENABLE(); + + if (heth->Init.MediaInterface == HAL_ETH_MII_MODE) + { + HAL_SBS_ETHInterfaceSelect(SBS_ETH_MII); + } + else + { + HAL_SBS_ETHInterfaceSelect(SBS_ETH_RMII); + } + + /* Dummy read to sync with ETH */ + (void)SBS->PMCR; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + SET_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (READ_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + } + + /*------------------ MDIO CSR Clock Range Configuration --------------------*/ + HAL_ETH_SetMDIOClockRange(heth); + + /*------------------ MAC LPI 1US Tic Counter Configuration --------------------*/ + WRITE_REG(heth->Instance->MAC1USTCR, (((uint32_t)HAL_RCC_GetHCLKFreq() / ETH_MAC_US_TICK) - 1U)); + + /*------------------ MAC, MTL and DMA default Configuration ----------------*/ + ETH_MACDMAConfig(heth); + + /* SET DSL to 64 bit */ + MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_DSL, ETH_DMACCR_DSL_64BIT); + + /* Set Receive Buffers Length (must be a multiple of 4) */ + if ((heth->Init.RxBuffLen % 0x4U) != 0x0U) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_PARAM; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + else + { + MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_RBSZ, ((heth->Init.RxBuffLen) << 1)); + } + + /*------------------ DMA Tx Descriptors Configuration ----------------------*/ + ETH_DMATxDescListInit(heth); + + /*------------------ DMA Rx Descriptors Configuration ----------------------*/ + ETH_DMARxDescListInit(heth); + + /*--------------------- ETHERNET MAC Address Configuration ------------------*/ + /* Set MAC addr bits 32 to 47 */ + heth->Instance->MACA0HR = (((uint32_t)(heth->Init.MACAddr[5]) << 8) | (uint32_t)heth->Init.MACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + heth->Instance->MACA0LR = (((uint32_t)(heth->Init.MACAddr[3]) << 24) | ((uint32_t)(heth->Init.MACAddr[2]) << 16) | + ((uint32_t)(heth->Init.MACAddr[1]) << 8) | (uint32_t)heth->Init.MACAddr[0]); + + /* Disable Rx MMC Interrupts */ + SET_BIT(heth->Instance->MMCRIMR, ETH_MMCRIMR_RXLPITRCIM | ETH_MMCRIMR_RXLPIUSCIM | \ + ETH_MMCRIMR_RXUCGPIM | ETH_MMCRIMR_RXALGNERPIM | ETH_MMCRIMR_RXCRCERPIM); + + /* Disable Tx MMC Interrupts */ + SET_BIT(heth->Instance->MMCTIMR, ETH_MMCTIMR_TXLPITRCIM | ETH_MMCTIMR_TXLPIUSCIM | \ + ETH_MMCTIMR_TXGPKTIM | ETH_MMCTIMR_TXMCOLGPIM | ETH_MMCTIMR_TXSCOLGPIM); + + heth->ErrorCode = HAL_ETH_ERROR_NONE; + heth->gState = HAL_ETH_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the ETH peripheral. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + if (heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* DeInit the low level hardware */ + heth->MspDeInitCallback(heth); +#else + + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + + /* Set ETH HAL state to Disabled */ + heth->gState = HAL_ETH_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = pCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = pCallback; + break; + + case HAL_ETH_EEE_CB_ID : + heth->EEECallback = pCallback; + break; + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callback is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = HAL_ETH_PMTCallback; + break; + + case HAL_ETH_EEE_CB_ID : + heth->EEECallback = HAL_ETH_EEECallback; + break; + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief ETH Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the ETH + data transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables Ethernet MAC and DMA reception and transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Clear Tx and Rx process stopped flags */ + heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS); + + heth->gState = HAL_ETH_STATE_STARTED; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* save IT mode to ETH Handle */ + heth->RxDescList.ItMode = 1U; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Clear Tx and Rx process stopped flags */ + heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Enable ETH DMA interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE | + ETH_DMACIER_FBEE | ETH_DMACIER_AIE | ETH_DMACIER_RBUE)); + + heth->gState = HAL_ETH_STATE_STARTED; + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t descindex; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE | + ETH_DMACIER_FBEE | ETH_DMACIER_AIE | ETH_DMACIER_RBUE)); + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Clear IOC bit to all Rx descriptors */ + for (descindex = 0; descindex < (uint32_t)ETH_RX_DESC_CNT; descindex++) + { + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex]; + CLEAR_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC); + } + + heth->RxDescList.ItMode = 0U; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in polling mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @param Timeout: timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout) +{ + uint32_t tickstart; + ETH_DMADescTypeDef *dmatxdesc; + + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE) + { + /* Set the ETH error code */ + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc]; + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + tickstart = HAL_GetTick(); + + /* Wait for data to be transmitted or timeout occurred */ + while ((dmatxdesc->DESC3 & ETH_DMATXNDESCWBF_OWN) != (uint32_t)RESET) + { + if ((heth->Instance->DMACSR & ETH_DMACSR_FBE) != (uint32_t)RESET) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + heth->DMAErrorCode = heth->Instance->DMACSR; + /* Return function status */ + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT; + /* Clear TX descriptor so that we can proceed */ + dmatxdesc->DESC3 = (ETH_DMATXNDESCWBF_FD | ETH_DMATXNDESCWBF_LD); + return HAL_ERROR; + } + } + } + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in interrupt mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig) +{ + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Save the packet pointer to release. */ + heth->TxDescList.CurrentPacketAddress = (uint32_t *)pTxConfig->pData; + + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE) + { + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + return HAL_OK; + + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Read a received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pAppBuff: Pointer to an application buffer to receive the packet. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff) +{ + uint32_t descidx; + ETH_DMADescTypeDef *dmarxdesc; + uint32_t desccnt = 0U; + uint32_t desccntmax; + uint32_t bufflength; + uint8_t rxdataready = 0U; + + if (pAppBuff == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState != HAL_ETH_STATE_STARTED) + { + return HAL_ERROR; + } + + descidx = heth->RxDescList.RxDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccntmax = ETH_RX_DESC_CNT - heth->RxDescList.RxBuildDescCnt; + + /* Check if descriptor is not owned by DMA */ + while ((READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_OWN) == (uint32_t)RESET) && (desccnt < desccntmax) + && (rxdataready == 0U)) + { + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_CTXT) != (uint32_t)RESET) + { + /* Get timestamp high */ + heth->RxDescList.TimeStamp.TimeStampHigh = dmarxdesc->DESC1; + /* Get timestamp low */ + heth->RxDescList.TimeStamp.TimeStampLow = dmarxdesc->DESC0; + } + if ((READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_FD) != (uint32_t)RESET) || (heth->RxDescList.pRxStart != NULL)) + { + /* Check if first descriptor */ + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_FD) != (uint32_t)RESET) + { + heth->RxDescList.RxDescCnt = 0; + heth->RxDescList.RxDataLength = 0; + } + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + bufflength = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_PL) - heth->RxDescList.RxDataLength; + + /* Check if last descriptor */ + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_LD) != (uint32_t)RESET) + { + /* Save Last descriptor index */ + heth->RxDescList.pRxLastRxDesc = dmarxdesc->DESC3; + + /* Packet ready */ + rxdataready = 1; + } + + /* Link data */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Link callback*/ + heth->rxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, bufflength); +#else + /* Link callback */ + HAL_ETH_RxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, (uint16_t) bufflength); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->RxDescList.RxDescCnt++; + heth->RxDescList.RxDataLength += bufflength; + + /* Clear buffer pointer */ + dmarxdesc->BackupAddr0 = 0; + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccnt++; + } + + heth->RxDescList.RxBuildDescCnt += desccnt; + if ((heth->RxDescList.RxBuildDescCnt) != 0U) + { + /* Update Descriptors */ + ETH_UpdateDescriptor(heth); + } + + heth->RxDescList.RxDescIdx = descidx; + + if (rxdataready == 1U) + { + /* Return received packet */ + *pAppBuff = heth->RxDescList.pRxStart; + /* Reset first element */ + heth->RxDescList.pRxStart = NULL; + + return HAL_OK; + } + + /* Packet not ready */ + return HAL_ERROR; +} + +/** + * @brief This function gives back Rx Desc of the last received Packet + * to the DMA, so ETH DMA will be able to use these descriptors + * to receive next Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth) +{ + uint32_t descidx; + uint32_t tailidx; + uint32_t desccount; + ETH_DMADescTypeDef *dmarxdesc; + uint8_t *buff = NULL; + uint8_t allocStatus = 1U; + + descidx = heth->RxDescList.RxBuildDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount = heth->RxDescList.RxBuildDescCnt; + + while ((desccount > 0U) && (allocStatus != 0U)) + { + /* Check if a buffer's attached the descriptor */ + if (READ_REG(dmarxdesc->BackupAddr0) == 0U) + { + /* Get a new buffer. */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Allocate callback*/ + heth->rxAllocateCallback(&buff); +#else + /* Allocate callback */ + HAL_ETH_RxAllocateCallback(&buff); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + if (buff == NULL) + { + allocStatus = 0U; + } + else + { + WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)buff); + WRITE_REG(dmarxdesc->DESC0, (uint32_t)buff); + } + } + + if (allocStatus != 0U) + { + + if (heth->RxDescList.ItMode != 0U) + { + WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V | ETH_DMARXNDESCRF_IOC); + } + else + { + WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V); + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount--; + } + } + + if (heth->RxDescList.RxBuildDescCnt != desccount) + { + /* Set the tail pointer index */ + tailidx = (descidx + 1U) % ETH_RX_DESC_CNT; + + /* DMB instruction to avoid race condition */ + __DMB(); + + /* Set the Tail pointer address */ + WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (tailidx)))); + + heth->RxDescList.RxBuildDescIdx = descidx; + heth->RxDescList.RxBuildDescCnt = desccount; + } +} + +/** + * @brief Register the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxAllocateCallback: pointer to function to alloc buffer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback) +{ + if (rxAllocateCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to allocate buffer */ + heth->rxAllocateCallback = rxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Rx Allocate callback. + * @param buff: pointer to allocated buffer + * @retval None + */ +__weak void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxAllocateCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Link callback. + * @param pStart: pointer to packet start + * @param pEnd: pointer to packet end + * @param buff: pointer to received data + * @param Length: received data length + * @retval None + */ +__weak void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(pStart); + UNUSED(pEnd); + UNUSED(buff); + UNUSED(Length); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxLinkCallback could be implemented in the user file + */ +} + +/** + * @brief Set the Rx link data function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxLinkCallback: pointer to function to link data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback) +{ + if (rxLinkCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to link data */ + heth->rxLinkCallback = rxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx link callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Get the error state of the last received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pErrorCode: pointer to uint32_t to hold the error code + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode) +{ + /* Get error bits. */ + *pErrorCode = READ_BIT(heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_ERRORS_MASK); + + return HAL_OK; +} + +/** + * @brief Set the Tx free function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txFreeCallback: pointer to function to release the packet + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback) +{ + if (txFreeCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to free transmmitted packet */ + heth->txFreeCallback = txFreeCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx free callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; + + return HAL_OK; +} + +/** + * @brief Tx Free callback. + * @param buff: pointer to buffer to free + * @retval None + */ +__weak void HAL_ETH_TxFreeCallback(uint32_t *buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxFreeCallback could be implemented in the user file + */ +} + +/** + * @brief Release transmitted Tx packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t numOfBuf = dmatxdesclist->BuffersInUse; + uint32_t idx = dmatxdesclist->releaseIndex; + uint8_t pktTxStatus = 1U; + uint8_t pktInUse; +#ifdef HAL_ETH_USE_PTP + ETH_TimeStampTypeDef *timestamp = &heth->TxTimestamp; +#endif /* HAL_ETH_USE_PTP */ + + /* Loop through buffers in use. */ + while ((numOfBuf != 0U) && (pktTxStatus != 0U)) + { + pktInUse = 1U; + numOfBuf--; + /* If no packet, just examine the next packet. */ + if (dmatxdesclist->PacketAddress[idx] == NULL) + { + /* No packet in use, skip to next. */ + INCR_TX_DESC_INDEX(idx, 1U); + pktInUse = 0U; + } + + if (pktInUse != 0U) + { + /* Determine if the packet has been transmitted. */ + if ((heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCRF_OWN) == 0U) + { +#ifdef HAL_ETH_USE_PTP + + /* Disable Ptp transmission */ + CLEAR_BIT(heth->Init.TxDesc[idx].DESC3, (0x40000000U)); + + if ((heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCWBF_LD) + && (heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCWBF_TTSS)) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->Init.TxDesc[idx].DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->Init.TxDesc[idx].DESC1; + } + else + { + timestamp->TimeStampHigh = timestamp->TimeStampLow = UINT32_MAX; + } +#endif /* HAL_ETH_USE_PTP */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered callbacks*/ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + heth->txPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + heth->txFreeCallback(dmatxdesclist->PacketAddress[idx]); +#else + /* Call callbacks */ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + HAL_ETH_TxPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + HAL_ETH_TxFreeCallback(dmatxdesclist->PacketAddress[idx]); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the entry in the in-use array. */ + dmatxdesclist->PacketAddress[idx] = NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + INCR_TX_DESC_INDEX(idx, 1U); + dmatxdesclist->BuffersInUse = numOfBuf; + dmatxdesclist->releaseIndex = idx; + } + else + { + /* Get out of the loop! */ + pktTxStatus = 0U; + } + } + } + return HAL_OK; +} + +#ifdef HAL_ETH_USE_PTP +/** + * @brief Set the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + uint32_t tmpTSCR; + ETH_TimeTypeDef time; + + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + + tmpTSCR = ptpconfig->Timestamp | + ((uint32_t)ptpconfig->TimestampUpdate << ETH_MACTSCR_TSUPDT_Pos) | + ((uint32_t)ptpconfig->TimestampAll << ETH_MACTSCR_TSENALL_Pos) | + ((uint32_t)ptpconfig->TimestampRolloverMode << ETH_MACTSCR_TSCTRLSSR_Pos) | + ((uint32_t)ptpconfig->TimestampV2 << ETH_MACTSCR_TSVER2ENA_Pos) | + ((uint32_t)ptpconfig->TimestampEthernet << ETH_MACTSCR_TSIPENA_Pos) | + ((uint32_t)ptpconfig->TimestampIPv6 << ETH_MACTSCR_TSIPV6ENA_Pos) | + ((uint32_t)ptpconfig->TimestampIPv4 << ETH_MACTSCR_TSIPV4ENA_Pos) | + ((uint32_t)ptpconfig->TimestampEvent << ETH_MACTSCR_TSEVNTENA_Pos) | + ((uint32_t)ptpconfig->TimestampMaster << ETH_MACTSCR_TSMSTRENA_Pos) | + ((uint32_t)ptpconfig->TimestampSnapshots << ETH_MACTSCR_SNAPTYPSEL_Pos) | + ((uint32_t)ptpconfig->TimestampFilter << ETH_MACTSCR_TSENMACADDR_Pos) | + ((uint32_t)ptpconfig->TimestampChecksumCorrection << ETH_MACTSCR_CSC_Pos) | + ((uint32_t)ptpconfig->TimestampStatusMode << ETH_MACTSCR_TXTSSTSM_Pos); + + /* Write to MACTSCR */ + MODIFY_REG(heth->Instance->MACTSCR, ETH_MACTSCR_MASK, tmpTSCR); + + /* Enable Timestamp */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSENA); + WRITE_REG(heth->Instance->MACSSIR, ptpconfig->TimestampSubsecondInc); + WRITE_REG(heth->Instance->MACTSAR, ptpconfig->TimestampAddend); + + /* Enable Timestamp */ + if (ptpconfig->TimestampAddendUpdate == ENABLE) + { + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSADDREG); + while ((heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG) != 0) + { + + } + } + + /* Ptp Init */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSINIT); + + /* Set PTP Configuration done */ + heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURED; + + /* Set Seconds */ + time.Seconds = heth->Instance->MACSTSR; + /* Set NanoSeconds */ + time.NanoSeconds = heth->Instance->MACSTNR; + + HAL_ETH_PTP_SetTime(heth, &time); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Get the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + ptpconfig->Timestamp = READ_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSENA); + ptpconfig->TimestampUpdate = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSCFUPDT) >> ETH_MACTSCR_TSUPDT_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampAll = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSENALL) >> ETH_MACTSCR_TSENALL_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampRolloverMode = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSCTRLSSR) >> ETH_MACTSCR_TSCTRLSSR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampV2 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSVER2ENA) >> ETH_MACTSCR_TSVER2ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEthernet = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPENA) >> ETH_MACTSCR_TSIPENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv6 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPV6ENA) >> ETH_MACTSCR_TSIPV6ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv4 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPV4ENA) >> ETH_MACTSCR_TSIPV4ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEvent = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSEVNTENA) >> ETH_MACTSCR_TSEVNTENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampMaster = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSMSTRENA) >> ETH_MACTSCR_TSMSTRENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampSnapshots = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_SNAPTYPSEL) >> ETH_MACTSCR_SNAPTYPSEL_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampFilter = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSENMACADDR) >> ETH_MACTSCR_TSENMACADDR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampChecksumCorrection = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_CSC) >> ETH_MACTSCR_CSC_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampStatusMode = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TXTSSTSM) >> ETH_MACTSCR_TXTSSTSM_Pos) > 0U) + ? ENABLE : DISABLE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to set + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Set Seconds */ + heth->Instance->MACSTSUR = time->Seconds; + + /* Set NanoSeconds */ + heth->Instance->MACSTNUR = time->NanoSeconds; + + /* the system time is updated */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSUPDT); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to get + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get Seconds */ + time->Seconds = heth->Instance->MACSTSR; + /* Get NanoSeconds */ + time->NanoSeconds = heth->Instance->MACSTNR; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Update time for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timeoffset: pointer to a ETH_PtpUpdateTypeDef structure that contains + * the time update information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + if (ptpoffsettype == HAL_ETH_PTP_NEGATIVE_UPDATE) + { + /* Set Seconds update */ + heth->Instance->MACSTSUR = ETH_MACSTSUR_VALUE - timeoffset->Seconds + 1U; + + if (READ_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSCTRLSSR) == ETH_MACTSCR_TSCTRLSSR) + { + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = ETH_MACSTNUR_VALUE - timeoffset->NanoSeconds; + } + else + { + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = ETH_MACSTSUR_VALUE - timeoffset->NanoSeconds + 1U; + } + } + else + { + /* Set Seconds update */ + heth->Instance->MACSTSUR = timeoffset->Seconds; + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = timeoffset->NanoSeconds; + } + + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSUPDT); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Insert Timestamp in transmission. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Enable Time Stamp transmission */ + SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_TTSE); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get transmission timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * transmission timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t idx = dmatxdesclist->releaseIndex; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[idx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = dmatxdesc->DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = dmatxdesc->DESC1; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get receive timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * receive timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->RxDescList.TimeStamp.TimeStampLow; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->RxDescList.TimeStamp.TimeStampHigh; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Register the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txPtpCallback: Function to handle Ptp transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback) +{ + if (txPtpCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + /* Set Function to handle Tx Ptp */ + heth->txPtpCallback = txPtpCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txPtpCallback = HAL_ETH_TxPtpCallback; + + return HAL_OK; +} + +/** + * @brief Tx Ptp callback. + * @param buff: pointer to application buffer + * @param timestamp: pointer to ETH_TimeStampTypeDef structure that contains + * transmission timestamp + * @retval None + */ +__weak void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxPtpCallback could be implemented in the user file + */ +} +#endif /* HAL_ETH_USE_PTP */ + +/** + * @brief This function handles ETH interrupt request. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + uint32_t mac_flag = READ_REG(heth->Instance->MACISR); + uint32_t dma_flag = READ_REG(heth->Instance->DMACSR); + uint32_t dma_itsource = READ_REG(heth->Instance->DMACIER); + uint32_t exti_flag = READ_REG(EXTI->RPR2); + + /* Packet received */ + if (((dma_flag & ETH_DMACSR_RI) != 0U) && ((dma_itsource & ETH_DMACIER_RIE) != 0U)) + { + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_RI | ETH_DMACSR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* Packet transmitted */ + if (((dma_flag & ETH_DMACSR_TI) != 0U) && ((dma_itsource & ETH_DMACIER_TIE) != 0U)) + { + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_TI | ETH_DMACSR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Transmit complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* ETH DMA Error */ + if (((dma_flag & ETH_DMACSR_AIS) != 0U) && ((dma_itsource & ETH_DMACIER_AIE) != 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + /* if fatal bus error occurred */ + if ((dma_flag & ETH_DMACSR_FBE) != 0U) + { + /* Get DMA error code */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS)); + + /* Disable all interrupts */ + __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMACIER_NIE | ETH_DMACIER_AIE); + + /* Set HAL state to ERROR */ + heth->gState = HAL_ETH_STATE_ERROR; + } + else + { + /* Get DMA error status */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | + ETH_DMACSR_RBU | ETH_DMACSR_AIS)); + + /* Clear the interrupt summary flag */ + __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | + ETH_DMACSR_RBU | ETH_DMACSR_AIS)); + } +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet DMA Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* ETH MAC Error IT */ + if (((mac_flag & ETH_MACIER_RXSTSIE) == ETH_MACIER_RXSTSIE) || \ + ((mac_flag & ETH_MACIER_TXSTSIE) == ETH_MACIER_TXSTSIE)) + { + heth->ErrorCode |= HAL_ETH_ERROR_MAC; + + /* Get MAC Rx Tx status and clear Status register pending bit */ + heth->MACErrorCode = READ_REG(heth->Instance->MACRXTXSR); + + heth->gState = HAL_ETH_STATE_ERROR; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->MACErrorCode = (uint32_t)(0x0U); + } + + /* ETH PMT IT */ + if ((mac_flag & ETH_MAC_PMT_IT) != 0U) + { + /* Get MAC Wake-up source and clear the status register pending bit */ + heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPCSR, (ETH_MACPCSR_RWKPRCVD | ETH_MACPCSR_MGKPRCVD)); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered PMT callback*/ + heth->PMTCallback(heth); +#else + /* Ethernet PMT callback */ + HAL_ETH_PMTCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACWakeUpEvent = (uint32_t)(0x0U); + } + + /* ETH EEE IT */ + if ((mac_flag & ETH_MAC_LPI_IT) != 0U) + { + /* Get MAC LPI interrupt source and clear the status register pending bit */ + heth->MACLPIEvent = READ_BIT(heth->Instance->MACPCSR, 0x0000000FU); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered EEE callback*/ + heth->EEECallback(heth); +#else + /* Ethernet EEE callback */ + HAL_ETH_EEECallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACLPIEvent = (uint32_t)(0x0U); + } + + /* check ETH WAKEUP exti flag */ + if ((exti_flag & ETH_WAKEUP_EXTI_LINE) != 0U) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet Power Management module IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_PMTCallback could be implemented in the user file + */ +} + +/** + * @brief Energy Efficient Etherent IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_EEECallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_EEECallback could be implemented in the user file + */ +} + +/** + * @brief ETH WAKEUP interrupt callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_WakeUpCallback could be implemented in the user file + */ +} + +/** + * @brief Read a PHY register + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param pRegValue: parameter to hold read value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue) +{ + uint32_t tickstart; + uint32_t tmpreg; + + /* Check for the Busy flag */ + if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET) + { + return HAL_ERROR; + } + + /* Get the MACMDIOAR value */ + WRITE_REG(tmpreg, heth->Instance->MACMDIOAR); + + /* Prepare the MDIO Address Register value + - Set the PHY device address + - Set the PHY register address + - Set the read mode + - Set the MII Busy bit */ + + MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD); + SET_BIT(tmpreg, ETH_MACMDIOAR_MB); + + /* Write the result value into the MDII Address register */ + WRITE_REG(heth->Instance->MACMDIOAR, tmpreg); + + tickstart = HAL_GetTick(); + + /* Wait for the Busy flag */ + while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT)) + { + return HAL_ERROR; + } + } + + /* Get MACMIIDR value */ + WRITE_REG(*pRegValue, (uint16_t)heth->Instance->MACMDIODR); + + return HAL_OK; +} + +/** + * @brief Writes to a PHY register. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param RegValue: the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue) +{ + uint32_t tickstart; + uint32_t tmpreg; + + /* Check for the Busy flag */ + if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET) + { + return HAL_ERROR; + } + + /* Get the MACMDIOAR value */ + WRITE_REG(tmpreg, heth->Instance->MACMDIOAR); + + /* Prepare the MDIO Address Register value + - Set the PHY device address + - Set the PHY register address + - Set the write mode + - Set the MII Busy bit */ + + MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR); + SET_BIT(tmpreg, ETH_MACMDIOAR_MB); + + /* Give the value to the MII data register */ + WRITE_REG(ETH->MACMDIODR, (uint16_t)RegValue); + + /* Write the result value into the MII Address register */ + WRITE_REG(ETH->MACMDIOAR, tmpreg); + + tickstart = HAL_GetTick(); + + /* Wait for the Busy flag */ + while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT)) + { + return HAL_ERROR; + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief ETH control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the ETH + peripheral. + +@endverbatim + * @{ + */ +/** + * @brief Get the configuration of the MAC and MTL subsystems. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold + * the configuration of the MAC. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + /* Get MAC parameters */ + macconf->PreambleLength = READ_BIT(heth->Instance->MACCR, ETH_MACCR_PRELEN); + macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL); + macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DR) >> 8) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DCRS) >> 9) > 0U) + ? ENABLE : DISABLE; + macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DO) >> 10) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseBeforeTransmit = ((READ_BIT(heth->Instance->MACCR, + ETH_MACCR_ECRSFD) >> 11) > 0U) ? ENABLE : DISABLE; + macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE; + macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM); + macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES); + macconf->JumboPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JE) >> 16) > 0U) ? ENABLE : DISABLE; + macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >> 17) == 0U) ? ENABLE : DISABLE; + macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >> 19) == 0U) ? ENABLE : DISABLE; + macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ACS) >> 20) > 0U) ? ENABLE : DISABLE; + macconf->CRCStripTypePacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CST) >> 21) > 0U) ? ENABLE : DISABLE; + macconf->Support2KPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_S2KP) >> 22) > 0U) ? ENABLE : DISABLE; + macconf->GiantPacketSizeLimitControl = ((READ_BIT(heth->Instance->MACCR, + ETH_MACCR_GPSLCE) >> 23) > 0U) ? ENABLE : DISABLE; + macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPG); + macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPC) >> 27) > 0U) ? ENABLE : DISABLE; + macconf->SourceAddrControl = READ_BIT(heth->Instance->MACCR, ETH_MACCR_SARC); + + macconf->GiantPacketSizeLimit = READ_BIT(heth->Instance->MACECR, ETH_MACECR_GPSL); + macconf->CRCCheckingRxPackets = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_DCRCC) >> 16) == 0U) ? ENABLE : DISABLE; + macconf->SlowProtocolDetect = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_SPEN) >> 17) > 0U) ? ENABLE : DISABLE; + macconf->UnicastSlowProtocolPacketDetect = ((READ_BIT(heth->Instance->MACECR, + ETH_MACECR_USP) >> 18) > 0U) ? ENABLE : DISABLE; + macconf->ExtendedInterPacketGap = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPGEN) >> 24) > 0U) + ? ENABLE : DISABLE; + macconf->ExtendedInterPacketGapVal = READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPG) >> 25; + + macconf->ProgrammableWatchdog = ((READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_PWE) >> 8) > 0U) ? ENABLE : DISABLE; + macconf->WatchdogTimeout = READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_WTO); + + macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_TFE) >> 1) > 0U) ? ENABLE : DISABLE; + macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_DZPQ) >> 7) == 0U) ? ENABLE : DISABLE; + macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PLT); + macconf->PauseTime = (READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PT) >> 16); + macconf->ReceiveFlowControl = (READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_RFE) > 0U) ? ENABLE : DISABLE; + macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_UP) >> 1) > 0U) + ? ENABLE : DISABLE; + + macconf->TransmitQueueMode = READ_BIT(heth->Instance->MTLTQOMR, (ETH_MTLTQOMR_TTC | ETH_MTLTQOMR_TSF)); + + macconf->ReceiveQueueMode = READ_BIT(heth->Instance->MTLRQOMR, (ETH_MTLRQOMR_RTC | ETH_MTLRQOMR_RSF)); + macconf->ForwardRxUndersizedGoodPacket = ((READ_BIT(heth->Instance->MTLRQOMR, + ETH_MTLRQOMR_FUP) >> 3) > 0U) ? ENABLE : DISABLE; + macconf->ForwardRxErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_FEP) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->DropTCPIPChecksumErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, + ETH_MTLRQOMR_DISTCPEF) >> 6) == 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Get the configuration of the DMA. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_AAL) >> 12) > 0U) ? ENABLE : DISABLE; + dmaconf->BurstMode = READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_FB | ETH_DMASBMR_MB); + dmaconf->RebuildINCRxBurst = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_RB) >> 15) > 0U) ? ENABLE : DISABLE; + + dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMAMR, (ETH_DMAMR_TXPR | ETH_DMAMR_PR | ETH_DMAMR_DA)); + + dmaconf->PBLx8Mode = ((READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_8PBL) >> 16) > 0U) ? ENABLE : DISABLE; + dmaconf->MaximumSegmentSize = READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_MSS); + + dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPF) >> 31) > 0U) ? ENABLE : DISABLE; + dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPBL); + + dmaconf->SecondPacketOperate = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_OSP) >> 4) > 0U) ? ENABLE : DISABLE; + dmaconf->TCPSegmentation = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TSE) >> 12) > 0U) ? ENABLE : DISABLE; + dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TPBL); + + return HAL_OK; +} + +/** + * @brief Set the MAC configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains + * the configuration of the MAC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetMACConfig(heth, macconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Set the ETH DMA configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetDMAConfig(heth, dmaconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configures the Clock range of ETH MDIO interface. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth) +{ + uint32_t hclk; + uint32_t tmpreg; + + /* Get the ETHERNET MACMDIOAR value */ + tmpreg = (heth->Instance)->MACMDIOAR; + + /* Clear CSR Clock Range bits */ + tmpreg &= ~ETH_MACMDIOAR_CR; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if (hclk < 35000000U) + { + /* CSR Clock Range between 0-35 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV16; + } + else if (hclk < 60000000U) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV26; + } + else if (hclk < 100000000U) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV42; + } + else if (hclk < 150000000U) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV62; + } + else if (hclk < 250000000U) + { + /* CSR Clock Range between 150-250 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV102; + } + else /* (hclk >= 250000000U) */ + { + /* CSR Clock >= 250 MHz */ + tmpreg |= (uint32_t)(ETH_MACMDIOAR_CR_DIV124); + } + + /* Configure the CSR Clock Range */ + (heth->Instance)->MACMDIOAR = (uint32_t)tmpreg; +} + +/** + * @brief Set the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + uint32_t filterconfig; + + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode | + ((uint32_t)pFilterConfig->HashUnicast << 1) | + ((uint32_t)pFilterConfig->HashMulticast << 2) | + ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) | + ((uint32_t)pFilterConfig->PassAllMulticast << 4) | + ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) | + ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) | + ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) | + ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) | + ((uint32_t)pFilterConfig->ReceiveAllMode << 31) | + pFilterConfig->ControlPacketsFilter); + + MODIFY_REG(heth->Instance->MACPFR, ETH_MACPFR_MASK, filterconfig); + + return HAL_OK; +} + +/** + * @brief Get the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PR)) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HUC) >> 1) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HMC) >> 2) > 0U) ? ENABLE : DISABLE; + pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, + ETH_MACPFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE; + pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PM) >> 4) > 0U) ? ENABLE : DISABLE; + pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_DBF) >> 5) == 0U) ? ENABLE : DISABLE; + pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PCF); + pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, + ETH_MACPFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE; + pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HPF) >> 10) > 0U) + ? ENABLE : DISABLE; + pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_RA) >> 31) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the source MAC Address to be matched. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param AddrNbr: The MAC address to configure + * This parameter must be a value of the following: + * ETH_MAC_ADDRESS1 + * ETH_MAC_ADDRESS2 + * ETH_MAC_ADDRESS3 + * @param pMACAddr: Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr) +{ + uint32_t macaddrlr; + uint32_t macaddrhr; + + if (pMACAddr == NULL) + { + return HAL_ERROR; + } + + /* Get mac addr high reg offset */ + macaddrhr = ((uint32_t) &(heth->Instance->MACA0HR) + AddrNbr); + /* Get mac addr low reg offset */ + macaddrlr = ((uint32_t) &(heth->Instance->MACA0LR) + AddrNbr); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) | + ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= (ETH_MACAHR_SA | ETH_MACAHR_AE); + + return HAL_OK; +} + +/** + * @brief Set the ETH Hash Table Value. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pHashTable: pointer to a table of two 32 bit values, that contains + * the 64 bits of the hash table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable) +{ + if (pHashTable == NULL) + { + return HAL_ERROR; + } + + heth->Instance->MACHT0R = pHashTable[0]; + heth->Instance->MACHT1R = pHashTable[1]; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Identifier for Rx packets + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ComparisonBits: 12 or 16 bit comparison mode + must be a value of @ref ETH_VLAN_Tag_Comparison + * @param VLANIdentifier: VLAN Identifier value + * @retval None + */ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier) +{ + if (ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT) + { + MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL, VLANIdentifier); + CLEAR_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV); + } + else + { + MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL_VID, VLANIdentifier); + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV); + } +} + +/** + * @brief Enters the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure + * that contains the Power Down configuration + * @retval None. + */ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, const ETH_PowerDownConfigTypeDef *pPowerDownConfig) +{ + uint32_t powerdownconfig; + + powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << 1) | + ((uint32_t)pPowerDownConfig->WakeUpPacket << 2) | + ((uint32_t)pPowerDownConfig->GlobalUnicast << 9) | + ((uint32_t)pPowerDownConfig->WakeUpForward << 10) | + ETH_MACPCSR_PWRDWN); + + /* Enable PMT interrupt */ + __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_PMTIE); + + MODIFY_REG(heth->Instance->MACPCSR, ETH_MACPCSR_MASK, powerdownconfig); +} + +/** + * @brief Exits from the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth) +{ + /* clear wake up sources */ + CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKPKTEN | ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | + ETH_MACPCSR_RWKPFE); + + if (READ_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN) != (uint32_t)RESET) + { + /* Exit power down mode */ + CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN); + } + + /* Disable PMT interrupt */ + __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_PMTIE); +} + +/** + * @brief Set the WakeUp filter. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilter: pointer to filter registers values + * @param Count: number of filter registers, must be from 1 to 8. + * @retval None. + */ +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count) +{ + uint32_t regindex; + + if (pFilter == NULL) + { + return HAL_ERROR; + } + + /* Reset Filter Pointer */ + SET_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKFILTRST); + + /* Wake up packet filter config */ + for (regindex = 0; regindex < Count; regindex++) + { + /* Write filter regs */ + WRITE_REG(heth->Instance->MACRWKPFR, pFilter[regindex]); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief ETH State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + ETH communication process, return Peripheral Errors occurred during communication + process + + +@endverbatim + * @{ + */ + +/** + * @brief Returns the ETH state. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth) +{ + return heth->gState; +} + +/** + * @brief Returns the ETH error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH Error Code + */ +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth) +{ + return heth->ErrorCode; +} + +/** + * @brief Returns the ETH DMA error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH DMA Error Code + */ +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth) +{ + return heth->DMAErrorCode; +} + +/** + * @brief Returns the ETH MAC error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC Error Code + */ +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth) +{ + return heth->MACErrorCode; +} + +/** + * @brief Returns the ETH MAC WakeUp event source + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event source + */ +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth) +{ + return heth->MACWakeUpEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions ETH Private Functions + * @{ + */ + +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf) +{ + uint32_t macregval; + + /*------------------------ MACCR Configuration --------------------*/ + macregval = (macconf->InterPacketGapVal | + macconf->SourceAddrControl | + ((uint32_t)macconf->ChecksumOffload << 27) | + ((uint32_t)macconf->GiantPacketSizeLimitControl << 23) | + ((uint32_t)macconf->Support2KPacket << 22) | + ((uint32_t)macconf->CRCStripTypePacket << 21) | + ((uint32_t)macconf->AutomaticPadCRCStrip << 20) | + ((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 19) | + ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 17) | + ((uint32_t)macconf->JumboPacket << 16) | + macconf->Speed | + macconf->DuplexMode | + ((uint32_t)macconf->LoopbackMode << 12) | + ((uint32_t)macconf->CarrierSenseBeforeTransmit << 11) | + ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 10) | + ((uint32_t)macconf->CarrierSenseDuringTransmit << 9) | + ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 8) | + macconf->BackOffLimit | + ((uint32_t)macconf->DeferralCheck << 4) | + macconf->PreambleLength); + + /* Write to MACCR */ + MODIFY_REG(heth->Instance->MACCR, ETH_MACCR_MASK, macregval); + + /*------------------------ MACECR Configuration --------------------*/ + macregval = ((macconf->ExtendedInterPacketGapVal << 25) | + ((uint32_t)macconf->ExtendedInterPacketGap << 24) | + ((uint32_t)macconf->UnicastSlowProtocolPacketDetect << 18) | + ((uint32_t)macconf->SlowProtocolDetect << 17) | + ((uint32_t)((macconf->CRCCheckingRxPackets == DISABLE) ? 1U : 0U) << 16) | + macconf->GiantPacketSizeLimit); + + /* Write to MACECR */ + MODIFY_REG(heth->Instance->MACECR, ETH_MACECR_MASK, macregval); + + /*------------------------ MACWTR Configuration --------------------*/ + macregval = (((uint32_t)macconf->ProgrammableWatchdog << 8) | + macconf->WatchdogTimeout); + + /* Write to MACWTR */ + MODIFY_REG(heth->Instance->MACWTR, ETH_MACWTR_MASK, macregval); + + /*------------------------ MACTFCR Configuration --------------------*/ + macregval = (((uint32_t)macconf->TransmitFlowControl << 1) | + macconf->PauseLowThreshold | + ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U) << 7) | + (macconf->PauseTime << 16)); + + /* Write to MACTFCR */ + MODIFY_REG(heth->Instance->MACTFCR, ETH_MACTFCR_MASK, macregval); + + /*------------------------ MACRFCR Configuration --------------------*/ + macregval = ((uint32_t)macconf->ReceiveFlowControl | + ((uint32_t)macconf->UnicastPausePacketDetect << 1)); + + /* Write to MACRFCR */ + MODIFY_REG(heth->Instance->MACRFCR, ETH_MACRFCR_MASK, macregval); + + /*------------------------ MTLTQOMR Configuration --------------------*/ + /* Write to MTLTQOMR */ + MODIFY_REG(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_MASK, macconf->TransmitQueueMode); + + /*------------------------ MTLRQOMR Configuration --------------------*/ + macregval = (macconf->ReceiveQueueMode | + ((uint32_t)((macconf->DropTCPIPChecksumErrorPacket == DISABLE) ? 1U : 0U) << 6) | + ((uint32_t)macconf->ForwardRxErrorPacket << 4) | + ((uint32_t)macconf->ForwardRxUndersizedGoodPacket << 3)); + + /* Write to MTLRQOMR */ + MODIFY_REG(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_MASK, macregval); +} + +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf) +{ + uint32_t dmaregval; + + /*------------------------ DMAMR Configuration --------------------*/ + MODIFY_REG(heth->Instance->DMAMR, ETH_DMAMR_MASK, dmaconf->DMAArbitration); + + /*------------------------ DMASBMR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->AddressAlignedBeats << 12) | + dmaconf->BurstMode | + ((uint32_t)dmaconf->RebuildINCRxBurst << 15)); + + MODIFY_REG(heth->Instance->DMASBMR, ETH_DMASBMR_MASK, dmaregval); + + /*------------------------ DMACCR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->PBLx8Mode << 16) | + dmaconf->MaximumSegmentSize); + MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_MASK, dmaregval); + + /*------------------------ DMACTCR Configuration --------------------*/ + dmaregval = (dmaconf->TxDMABurstLength | + ((uint32_t)dmaconf->SecondPacketOperate << 4) | + ((uint32_t)dmaconf->TCPSegmentation << 12)); + + MODIFY_REG(heth->Instance->DMACTCR, ETH_DMACTCR_MASK, dmaregval); + + /*------------------------ DMACRCR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->FlushRxPacket << 31) | + dmaconf->RxDMABurstLength); + + /* Write to DMACRCR */ + MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_MASK, dmaregval); +} + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth) +{ + ETH_MACConfigTypeDef macDefaultConf; + ETH_DMAConfigTypeDef dmaDefaultConf; + + /*--------------- ETHERNET MAC registers default Configuration --------------*/ + macDefaultConf.AutomaticPadCRCStrip = ENABLE; + macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10; + macDefaultConf.CarrierSenseBeforeTransmit = DISABLE; + macDefaultConf.CarrierSenseDuringTransmit = DISABLE; + macDefaultConf.ChecksumOffload = ENABLE; + macDefaultConf.CRCCheckingRxPackets = ENABLE; + macDefaultConf.CRCStripTypePacket = ENABLE; + macDefaultConf.DeferralCheck = DISABLE; + macDefaultConf.DropTCPIPChecksumErrorPacket = ENABLE; + macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE; + macDefaultConf.ExtendedInterPacketGap = DISABLE; + macDefaultConf.ExtendedInterPacketGapVal = 0x0U; + macDefaultConf.ForwardRxErrorPacket = DISABLE; + macDefaultConf.ForwardRxUndersizedGoodPacket = DISABLE; + macDefaultConf.GiantPacketSizeLimit = 0x618U; + macDefaultConf.GiantPacketSizeLimitControl = DISABLE; + macDefaultConf.InterPacketGapVal = ETH_INTERPACKETGAP_96BIT; + macDefaultConf.Jabber = ENABLE; + macDefaultConf.JumboPacket = DISABLE; + macDefaultConf.LoopbackMode = DISABLE; + macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS_4; + macDefaultConf.PauseTime = 0x0U; + macDefaultConf.PreambleLength = ETH_PREAMBLELENGTH_7; + macDefaultConf.ProgrammableWatchdog = DISABLE; + macDefaultConf.ReceiveFlowControl = DISABLE; + macDefaultConf.ReceiveOwn = ENABLE; + macDefaultConf.ReceiveQueueMode = ETH_RECEIVESTOREFORWARD; + macDefaultConf.RetryTransmission = ENABLE; + macDefaultConf.SlowProtocolDetect = DISABLE; + macDefaultConf.SourceAddrControl = ETH_SOURCEADDRESS_REPLACE_ADDR0; + macDefaultConf.Speed = ETH_SPEED_100M; + macDefaultConf.Support2KPacket = DISABLE; + macDefaultConf.TransmitQueueMode = ETH_TRANSMITSTOREFORWARD; + macDefaultConf.TransmitFlowControl = DISABLE; + macDefaultConf.UnicastPausePacketDetect = DISABLE; + macDefaultConf.UnicastSlowProtocolPacketDetect = DISABLE; + macDefaultConf.Watchdog = ENABLE; + macDefaultConf.WatchdogTimeout = ETH_MACWTR_WTO_2KB; + macDefaultConf.ZeroQuantaPause = ENABLE; + + /* MAC default configuration */ + ETH_SetMACConfig(heth, &macDefaultConf); + + /*--------------- ETHERNET DMA registers default Configuration --------------*/ + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1; + dmaDefaultConf.FlushRxPacket = DISABLE; + dmaDefaultConf.PBLx8Mode = DISABLE; + dmaDefaultConf.RebuildINCRxBurst = DISABLE; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.SecondPacketOperate = DISABLE; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.TCPSegmentation = DISABLE; + dmaDefaultConf.MaximumSegmentSize = ETH_SEGMENT_SIZE_DEFAULT; + + /* DMA default configuration */ + ETH_SetDMAConfig(heth, &dmaDefaultConf); +} + +/** + * @brief Initializes the DMA Tx descriptors. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmatxdesc; + uint32_t i; + + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++) + { + dmatxdesc = heth->Init.TxDesc + i; + + WRITE_REG(dmatxdesc->DESC0, 0x0U); + WRITE_REG(dmatxdesc->DESC1, 0x0U); + WRITE_REG(dmatxdesc->DESC2, 0x0U); + WRITE_REG(dmatxdesc->DESC3, 0x0U); + + WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc); + + } + + heth->TxDescList.CurTxDesc = 0; + + /* Set Transmit Descriptor Ring Length */ + WRITE_REG(heth->Instance->DMACTDRLR, (ETH_TX_DESC_CNT - 1U)); + + /* Set Transmit Descriptor List Address */ + WRITE_REG(heth->Instance->DMACTDLAR, (uint32_t) heth->Init.TxDesc); + + /* Set Transmit Descriptor Tail pointer */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t) heth->Init.TxDesc); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t i; + + for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++) + { + dmarxdesc = heth->Init.RxDesc + i; + + WRITE_REG(dmarxdesc->DESC0, 0x0U); + WRITE_REG(dmarxdesc->DESC1, 0x0U); + WRITE_REG(dmarxdesc->DESC2, 0x0U); + WRITE_REG(dmarxdesc->DESC3, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr0, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr1, 0x0U); + + /* Set Rx descritors addresses */ + WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc); + + } + + WRITE_REG(heth->RxDescList.RxDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxDescCnt, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0U); + WRITE_REG(heth->RxDescList.ItMode, 0U); + + /* Set Receive Descriptor Ring Length */ + WRITE_REG(heth->Instance->DMACRDRLR, ((uint32_t)(ETH_RX_DESC_CNT - 1U))); + + /* Set Receive Descriptor List Address */ + WRITE_REG(heth->Instance->DMACRDLAR, (uint32_t) heth->Init.RxDesc); + + /* Set Receive Descriptor Tail pointer Address */ + WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (uint32_t)(ETH_RX_DESC_CNT - 1U)))); +} + +/** + * @brief Prepare Tx DMA descriptor before transmission. + * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Tx packet configuration + * @param ItMode: Enable or disable Tx EOT interrept + * @retval Status + */ +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + uint32_t firstdescidx = dmatxdesclist->CurTxDesc; + uint32_t idx; + uint32_t descnbr = 0; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer; + uint32_t bd_count = 0; + uint32_t primask_bit; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + return HAL_ETH_ERROR_BUSY; + } + + /***************************************************************************/ + /***************** Context descriptor configuration (Optional) **********/ + /***************************************************************************/ + /* If VLAN tag is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + { + /* Set vlan tag value */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_VT, pTxConfig->VlanTag); + /* Set vlan tag valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_VLTV); + /* Set the descriptor as the vlan input source */ + SET_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI); + + /* if inner VLAN is enabled */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_INNERVLANTAG) != (uint32_t)RESET) + { + /* Set inner vlan tag value */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_IVT, (pTxConfig->InnerVlanTag << 16)); + /* Set inner vlan tag valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_IVLTV); + + /* Set Vlan Tag control */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_IVTIR, pTxConfig->InnerVlanCtrl); + + /* Set the descriptor as the inner vlan input source */ + SET_BIT(heth->Instance->MACIVIR, ETH_MACIVIR_VLTI); + /* Enable double VLAN processing */ + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP); + } + } + + /* if tcp segmentation is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set MSS value */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_MSS, pTxConfig->MaxSegmentSize); + /* Set MSS valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_TCMSSV); + } + + if ((READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + || (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET)) + { + /* Set as context descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_CTXT); + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set own bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN); + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + descnbr += 1U; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if (READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) + { + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[firstdescidx]; + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Clear own bit */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN); + + return HAL_ETH_ERROR_BUSY; + } + } + + /***************************************************************************/ + /***************** Normal descriptors configuration *****************/ + /***************************************************************************/ + + descnbr += 1U; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer); + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len); + + if (txbuffer->next != NULL) + { + txbuffer = txbuffer->next; + /* Set buffer 2 address */ + WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16)); + } + else + { + WRITE_REG(dmatxdesc->DESC1, 0x0U); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set TCP Header length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_THL, (pTxConfig->TCPHeaderLen << 19)); + /* Set TCP payload length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen); + /* Set TCP Segmentation Enabled bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE); + } + else + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CPC, pTxConfig->CRCPadCtrl); + } + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + { + /* Set Vlan Tag control */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_VTIR, pTxConfig->VlanCtrl); + } + + /* Mark it as First Descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD); + /* Mark it as NORMAL descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT); + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* set OWN bit of FIRST descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + + /* If source address insertion/replacement is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_SAIC) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_SAIC, pTxConfig->SrcAddrCtrl); + } + + /* only if the packet is split into more than one descriptors > 1 */ + while (txbuffer->next != NULL) + { + /* Clear the LD bit of previous descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD); + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* Clear the FD bit of new Descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD); + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN) == ETH_DMATXNDESCRF_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + descidx = firstdescidx; + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* clear previous desc own bit */ + for (idx = 0; idx < descnbr; idx ++) + { + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + } + + return HAL_ETH_ERROR_BUSY; + } + + descnbr += 1U; + + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer); + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len); + + if (txbuffer->next != NULL) + { + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + /* Set buffer 2 address */ + WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16)); + } + else + { + WRITE_REG(dmatxdesc->DESC1, 0x0U); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set TCP payload length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen); + /* Set TCP Segmentation Enabled bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE); + } + else + { + /* Set the packet length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != (uint32_t)RESET) + { + /* Checksum Insertion Control */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl); + } + } + + bd_count += 1U; + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set Own bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + /* Mark it as NORMAL descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT); + } + + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC); + } + + /* Mark it as LAST descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD); + /* Save the current packet address to expose it to the application */ + dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress; + + dmatxdesclist->CurTxDesc = descidx; + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1); + + dmatxdesclist->BuffersInUse += bd_count + 1U; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); + + /* Return function status */ + return HAL_ETH_ERROR_NONE; +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->ErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak ErrorCallback */ + heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */ + heth->EEECallback = HAL_ETH_EEECallback; /* Legacy weak EEECallback */ + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; /* Legacy weak RxLinkCallback */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; /* Legacy weak TxFreeCallback */ +#ifdef HAL_ETH_USE_PTP + heth->txPtpCallback = HAL_ETH_TxPtpCallback; /* Legacy weak TxPtpCallback */ +#endif /* HAL_ETH_USE_PTP */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; /* Legacy weak RxAllocateCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ + +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.h new file mode 100644 index 0000000000..c32b34c6ac --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth.h @@ -0,0 +1,1823 @@ +/** + ****************************************************************************** + * @file stm32h5xx_hal_eth.h + * @author MCD Application Team + * @brief Header file of ETH HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H5xx_HAL_ETH_H +#define STM32H5xx_HAL_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h5xx_hal_def.h" + +#if defined(ETH) + +/** @addtogroup STM32H5xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +#ifndef ETH_TX_DESC_CNT +#define ETH_TX_DESC_CNT 4U +#endif /* ETH_TX_DESC_CNT */ + +#ifndef ETH_RX_DESC_CNT +#define ETH_RX_DESC_CNT 4U +#endif /* ETH_RX_DESC_CNT */ + +#ifndef ETH_SWRESET_TIMEOUT +#define ETH_SWRESET_TIMEOUT 500U +#endif /* ETH_SWRESET_TIMEOUT */ + +#ifndef ETH_MDIO_BUS_TIMEOUT +#define ETH_MDIO_BUS_TIMEOUT 1000U +#endif /* ETH_MDIO_BUS_TIMEOUT */ + +#ifndef ETH_MAC_US_TICK +#define ETH_MAC_US_TICK 1000000U +#endif /* ETH_MAC_US_TICK */ + +/*********************** Descriptors struct def section ************************/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief ETH DMA Descriptor structure definition + */ +typedef struct +{ + __IO uint32_t DESC0; + __IO uint32_t DESC1; + __IO uint32_t DESC2; + __IO uint32_t DESC3; + uint32_t BackupAddr0; /* used to store rx buffer 1 address */ + uint32_t BackupAddr1; /* used to store rx buffer 2 address */ +} ETH_DMADescTypeDef; +/** + * + */ + +/** + * @brief ETH Buffers List structure definition + */ +typedef struct __ETH_BufferTypeDef +{ + uint8_t *buffer; /*gState = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_ETH_STATE_RESET; \ + } while(0) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACIER &= ~(__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT source enabled or disabled. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The ETH DMA IT Source enabled or disabled + */ +#define __HAL_ETH_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) \ + (((__HANDLE__)->Instance->DMACIER & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The state of ETH DMA IT (SET or RESET) + */ +#define __HAL_ETH_DMA_GET_IT(__HANDLE__, __INTERRUPT__) \ + (((__HANDLE__)->Instance->DMACSR & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACSR = (__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMACSR &( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Clears the specified ETHERNET DMA flag. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMACSR = ( __FLAG__)) + +/** + * @brief Enables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ + +#define __HAL_ETH_MAC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ +#define __HAL_ETH_MAC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER &= ~(__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __INTERRUPT__: specifies the flag to check. @ref ETH_MAC_Interrupts + * @retval The state of ETH MAC IT (SET or RESET). + */ +#define __HAL_ETH_MAC_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MACISR &\ + ( __INTERRUPT__)) == ( __INTERRUPT__)) + +/*!< External interrupt line 46 Connected to the ETH wakeup EXTI Line */ +#define ETH_WAKEUP_EXTI_LINE 0x00004000U /* !< 46 - 32 = 14 */ + +/** + * @brief Enable the ETH WAKEUP Exti Line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT(__EXTI_LINE__) (EXTI->IMR2 |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI->RPR2 & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI->RPR2 = (__EXTI_LINE__)) + +/** + * @brief enable rising edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE(__EXTI_LINE__) (EXTI->FTSR2 &= ~(__EXTI_LINE__)); \ + (EXTI->RTSR2 |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR2 &= ~(__EXTI_LINE__));\ + (EXTI->FTSR2 |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR2 |= (__EXTI_LINE__));\ + (EXTI->FTSR2 |= (__EXTI_LINE__)) + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER2 |= (__EXTI_LINE__)) +#define __HAL_ETH_GET_PTP_CONTROL(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->MACTSCR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) +#define __HAL_ETH_SET_PTP_CONTROL(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->MACTSCR |= (__FLAG__)) + +/** + * @} + */ + +/* Include ETH HAL Extension module */ +#include "stm32h5xx_hal_eth_ex.h" + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de initialization functions **********************************/ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth); + +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff); +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode); +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth); + +#ifdef HAL_ETH_USE_PTP +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset); +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth); +#endif /* HAL_ETH_USE_PTP */ + +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout); +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig); + +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue); +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue); + +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_EEECallback(ETH_HandleTypeDef *heth); +void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxAllocateCallback(uint8_t **buff); +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length); +void HAL_ETH_TxFreeCallback(uint32_t *buff); +void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp); +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions **********************************************/ +/* MAC & DMA Configuration APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, + uint32_t VLANIdentifier); + +/* MAC L2 Packet Filtering APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable); +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr); + +/* MAC Power Down APIs *****************************************************/ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, + const ETH_PowerDownConfigTypeDef *pPowerDownConfig); +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count); + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_ETH_H */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.c b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.c new file mode 100644 index 0000000000..e4fa9d76df --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.c @@ -0,0 +1,660 @@ +/** + ****************************************************************************** + * @file stm32h5xx_hal_eth_ex.c + * @author MCD Application Team + * @brief ETH HAL Extended module driver. + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h5xx_hal.h" + +/** @addtogroup STM32H5xx_HAL_Driver + * @{ + */ + +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETHEx ETHEx + * @brief ETH HAL Extended module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup ETHEx_Private_Constants ETHEx Private Constants + * @{ + */ +#define ETH_MACL4CR_MASK (ETH_MACL3L4CR_L4PEN | ETH_MACL3L4CR_L4SPM | \ + ETH_MACL3L4CR_L4SPIM | ETH_MACL3L4CR_L4DPM | \ + ETH_MACL3L4CR_L4DPIM) + +#define ETH_MACL3CR_MASK (ETH_MACL3L4CR_L3PEN | ETH_MACL3L4CR_L3SAM | \ + ETH_MACL3L4CR_L3SAIM | ETH_MACL3L4CR_L3DAM | \ + ETH_MACL3L4CR_L3DAIM | ETH_MACL3L4CR_L3HSBM | \ + ETH_MACL3L4CR_L3HDBM) + +#define ETH_MACRXVLAN_MASK (ETH_MACVTR_EIVLRXS | ETH_MACVTR_EIVLS | \ + ETH_MACVTR_ERIVLT | ETH_MACVTR_EDVLP | \ + ETH_MACVTR_VTHM | ETH_MACVTR_EVLRXS | \ + ETH_MACVTR_EVLS | ETH_MACVTR_DOVLTC | \ + ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL | \ + ETH_MACVTR_VTIM | ETH_MACVTR_ETV) + +#define ETH_MACTXVLAN_MASK (ETH_MACVIR_VLTI | ETH_MACVIR_CSVL | \ + ETH_MACVIR_VLP | ETH_MACVIR_VLC) + +#define ETH_MAC_L4_SRSP_MASK 0x0000FFFFU +#define ETH_MAC_L4_DSTP_MASK 0xFFFF0000U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Functions ETH Extended Exported Functions + * @{ + */ + +/** @defgroup ETHEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure ARP offload module + (+) Configure L3 and L4 filters + (+) Configure Extended VLAN features + (+) Configure Energy Efficient Ethernet module + +@endverbatim + * @{ + */ + +/** + * @brief Enables ARP Offload. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ + +void HAL_ETHEx_EnableARPOffload(ETH_HandleTypeDef *heth) +{ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_ARP); +} + +/** + * @brief Disables ARP Offload. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETHEx_DisableARPOffload(ETH_HandleTypeDef *heth) +{ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_ARP); +} + +/** + * @brief Set the ARP Match IP address + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param IpAddress: IP Address to be matched for incoming ARP requests + * @retval None + */ +void HAL_ETHEx_SetARPAddressMatch(ETH_HandleTypeDef *heth, uint32_t IpAddress) +{ + WRITE_REG(heth->Instance->MACARPAR, IpAddress); +} + +/** + * @brief Configures the L4 Filter, this function allow to: + * set the layer 4 protocol to be matched (TCP or UDP) + * enable/disable L4 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L4 filter to configured, this parameter must be one of the following + * ETH_L4_FILTER_0 + * ETH_L4_FILTER_1 + * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure + * that contains L4 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L4FilterConfigTypeDef *pL4FilterConfig) +{ + if (pL4FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L4_FILTER_0) + { + /* Write configuration to MACL3L4C0R register */ + MODIFY_REG(heth->Instance->MACL3L4C0R, ETH_MACL4CR_MASK, (pL4FilterConfig->Protocol | + pL4FilterConfig->SrcPortFilterMatch | + pL4FilterConfig->DestPortFilterMatch)); + + /* Write configuration to MACL4A0R register */ + WRITE_REG(heth->Instance->MACL4A0R, (pL4FilterConfig->SourcePort | (pL4FilterConfig->DestinationPort << 16))); + + } + else /* Filter == ETH_L4_FILTER_1 */ + { + /* Write configuration to MACL3L4C1R register */ + MODIFY_REG(heth->Instance->MACL3L4C1R, ETH_MACL4CR_MASK, (pL4FilterConfig->Protocol | + pL4FilterConfig->SrcPortFilterMatch | + pL4FilterConfig->DestPortFilterMatch)); + + /* Write configuration to MACL4A1R register */ + WRITE_REG(heth->Instance->MACL4A1R, (pL4FilterConfig->SourcePort | (pL4FilterConfig->DestinationPort << 16))); + } + + /* Enable L4 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); + + return HAL_OK; +} + +/** + * @brief Configures the L4 Filter, this function allow to: + * set the layer 4 protocol to be matched (TCP or UDP) + * enable/disable L4 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L4 filter to configured, this parameter must be one of the following + * ETH_L4_FILTER_0 + * ETH_L4_FILTER_1 + * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure + * that contains L4 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetL4FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L4FilterConfigTypeDef *pL4FilterConfig) +{ + if (pL4FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L4_FILTER_0) + { + /* Get configuration from MACL3L4C0R register */ + pL4FilterConfig->Protocol = READ_BIT(heth->Instance->MACL3L4C0R, ETH_MACL3L4CR_L4PEN); + pL4FilterConfig->DestPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C0R, + (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM)); + pL4FilterConfig->SrcPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C0R, + (ETH_MACL3L4CR_L4SPM | ETH_MACL3L4CR_L4SPIM)); + + /* Get configuration from MACL4A0R register */ + pL4FilterConfig->DestinationPort = (READ_BIT(heth->Instance->MACL4A0R, ETH_MAC_L4_DSTP_MASK) >> 16); + pL4FilterConfig->SourcePort = READ_BIT(heth->Instance->MACL4A0R, ETH_MAC_L4_SRSP_MASK); + } + else /* Filter == ETH_L4_FILTER_1 */ + { + /* Get configuration from MACL3L4C1R register */ + pL4FilterConfig->Protocol = READ_BIT(heth->Instance->MACL3L4C1R, ETH_MACL3L4CR_L4PEN); + pL4FilterConfig->DestPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C1R, + (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM)); + pL4FilterConfig->SrcPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C1R, + (ETH_MACL3L4CR_L4SPM | ETH_MACL3L4CR_L4SPIM)); + + /* Get configuration from MACL4A1R register */ + pL4FilterConfig->DestinationPort = (READ_BIT(heth->Instance->MACL4A1R, ETH_MAC_L4_DSTP_MASK) >> 16); + pL4FilterConfig->SourcePort = READ_BIT(heth->Instance->MACL4A1R, ETH_MAC_L4_SRSP_MASK); + } + + return HAL_OK; +} + +/** + * @brief Configures the L3 Filter, this function allow to: + * set the layer 3 protocol to be matched (IPv4 or IPv6) + * enable/disable L3 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L3 filter to configured, this parameter must be one of the following + * ETH_L3_FILTER_0 + * ETH_L3_FILTER_1 + * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure + * that contains L3 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L3FilterConfigTypeDef *pL3FilterConfig) +{ + if (pL3FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L3_FILTER_0) + { + /* Write configuration to MACL3L4C0R register */ + MODIFY_REG(heth->Instance->MACL3L4C0R, ETH_MACL3CR_MASK, (pL3FilterConfig->Protocol | + pL3FilterConfig->SrcAddrFilterMatch | + pL3FilterConfig->DestAddrFilterMatch | + (pL3FilterConfig->SrcAddrHigherBitsMatch << 6) | + (pL3FilterConfig->DestAddrHigherBitsMatch << 11))); + } + else /* Filter == ETH_L3_FILTER_1 */ + { + /* Write configuration to MACL3L4C1R register */ + MODIFY_REG(heth->Instance->MACL3L4C1R, ETH_MACL3CR_MASK, (pL3FilterConfig->Protocol | + pL3FilterConfig->SrcAddrFilterMatch | + pL3FilterConfig->DestAddrFilterMatch | + (pL3FilterConfig->SrcAddrHigherBitsMatch << 6) | + (pL3FilterConfig->DestAddrHigherBitsMatch << 11))); + } + + if (Filter == ETH_L3_FILTER_0) + { + /* Check if IPv6 protocol is selected */ + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + /* Set the IPv6 address match */ + /* Set Bits[31:0] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A0R0R, pL3FilterConfig->Ip6Addr[0]); + /* Set Bits[63:32] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R0R, pL3FilterConfig->Ip6Addr[1]); + /* update Bits[95:64] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A2R0R, pL3FilterConfig->Ip6Addr[2]); + /* update Bits[127:96] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A3R0R, pL3FilterConfig->Ip6Addr[3]); + } + else /* IPv4 protocol is selected */ + { + /* Set the IPv4 source address match */ + WRITE_REG(heth->Instance->MACL3A0R0R, pL3FilterConfig->Ip4SrcAddr); + /* Set the IPv4 destination address match */ + WRITE_REG(heth->Instance->MACL3A1R0R, pL3FilterConfig->Ip4DestAddr); + } + } + else /* Filter == ETH_L3_FILTER_1 */ + { + /* Check if IPv6 protocol is selected */ + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + /* Set the IPv6 address match */ + /* Set Bits[31:0] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip6Addr[0]); + /* Set Bits[63:32] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[1]); + /* update Bits[95:64] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[2]); + /* update Bits[127:96] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[3]); + } + else /* IPv4 protocol is selected */ + { + /* Set the IPv4 source address match */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip4SrcAddr); + /* Set the IPv4 destination address match */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip4DestAddr); + + } + } + + /* Enable L3 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); + + return HAL_OK; +} + +/** + * @brief Configures the L3 Filter, this function allow to: + * set the layer 3 protocol to be matched (IPv4 or IPv6) + * enable/disable L3 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L3 filter to configured, this parameter must be one of the following + * ETH_L3_FILTER_0 + * ETH_L3_FILTER_1 + * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure + * that will contain the L3 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetL3FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L3FilterConfigTypeDef *pL3FilterConfig) +{ + if (pL3FilterConfig == NULL) + { + return HAL_ERROR; + } + pL3FilterConfig->Protocol = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3PEN); + pL3FilterConfig->SrcAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + (ETH_MACL3L4CR_L3SAM | ETH_MACL3L4CR_L3SAIM)); + pL3FilterConfig->DestAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + (ETH_MACL3L4CR_L3DAM | ETH_MACL3L4CR_L3DAIM)); + pL3FilterConfig->SrcAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3HSBM) >> 6); + pL3FilterConfig->DestAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3HDBM) >> 11); + + if (Filter == ETH_L3_FILTER_0) + { + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + WRITE_REG(pL3FilterConfig->Ip6Addr[0], heth->Instance->MACL3A0R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[1], heth->Instance->MACL3A1R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[2], heth->Instance->MACL3A2R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[3], heth->Instance->MACL3A3R0R); + } + else + { + WRITE_REG(pL3FilterConfig->Ip4SrcAddr, heth->Instance->MACL3A0R0R); + WRITE_REG(pL3FilterConfig->Ip4DestAddr, heth->Instance->MACL3A1R0R); + } + } + else /* ETH_L3_FILTER_1 */ + { + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + WRITE_REG(pL3FilterConfig->Ip6Addr[0], heth->Instance->MACL3A0R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[1], heth->Instance->MACL3A1R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[2], heth->Instance->MACL3A2R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[3], heth->Instance->MACL3A3R1R); + } + else + { + WRITE_REG(pL3FilterConfig->Ip4SrcAddr, heth->Instance->MACL3A0R1R); + WRITE_REG(pL3FilterConfig->Ip4DestAddr, heth->Instance->MACL3A1R1R); + } + } + + return HAL_OK; +} + +/** + * @brief Enables L3 and L4 filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_EnableL3L4Filtering(ETH_HandleTypeDef *heth) +{ + /* Enable L3/L4 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); +} + +/** + * @brief Disables L3 and L4 filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_DisableL3L4Filtering(ETH_HandleTypeDef *heth) +{ + /* Disable L3/L4 filter */ + CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); +} + +/** + * @brief Get the VLAN Configuration for Receive Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure + * that will contain the VLAN filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetRxVLANConfig(const ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + pVlanConfig->InnerVLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EIVLRXS) >> 31) == 0U) ? DISABLE : ENABLE; + pVlanConfig->StripInnerVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EIVLS); + pVlanConfig->InnerVLANTag = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_ERIVLT) >> 27) == 0U) ? DISABLE : ENABLE; + pVlanConfig->DoubleVLANProcessing = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EDVLP) >> 26) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagHashTableMatch = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_VTHM) >> 25) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EVLRXS) >> 24) == 0U) ? DISABLE : ENABLE; + pVlanConfig->StripVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EVLS); + pVlanConfig->VLANTypeCheck = READ_BIT(heth->Instance->MACVTR, + (ETH_MACVTR_DOVLTC | ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL)); + pVlanConfig->VLANTagInverceMatch = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_VTIM) >> 17) == 0U) + ? DISABLE : ENABLE; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Configuration for Receive Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure + * that contains VLAN filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + /* Write config to MACVTR */ + MODIFY_REG(heth->Instance->MACVTR, ETH_MACRXVLAN_MASK, (((uint32_t)pVlanConfig->InnerVLANTagInStatus << 31) | + pVlanConfig->StripInnerVLANTag | + ((uint32_t)pVlanConfig->InnerVLANTag << 27) | + ((uint32_t)pVlanConfig->DoubleVLANProcessing << 26) | + ((uint32_t)pVlanConfig->VLANTagHashTableMatch << 25) | + ((uint32_t)pVlanConfig->VLANTagInStatus << 24) | + pVlanConfig->StripVLANTag | + pVlanConfig->VLANTypeCheck | + ((uint32_t)pVlanConfig->VLANTagInverceMatch << 17))); + + return HAL_OK; +} + +/** + * @brief Set the VLAN Hash Table + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANHashTable: VLAN hash table 16 bit value + * @retval None + */ +void HAL_ETHEx_SetVLANHashTable(ETH_HandleTypeDef *heth, uint32_t VLANHashTable) +{ + MODIFY_REG(heth->Instance->MACVHTR, ETH_MACVHTR_VLHT, VLANHashTable); +} + +/** + * @brief Get the VLAN Configuration for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure + * that will contain the Tx VLAN filter configuration. + * @retval HAL Status. + */ +HAL_StatusTypeDef HAL_ETHEx_GetTxVLANConfig(const ETH_HandleTypeDef *heth, uint32_t VLANTag, + ETH_TxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE; + pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACIVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC)); + } + else + { + pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE; + pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC)); + } + + return HAL_OK;; +} + +/** + * @brief Set the VLAN Configuration for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure + * that contains Tx VLAN filter configuration. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETHEx_SetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag, + const ETH_TxVLANConfigTypeDef *pVlanConfig) +{ + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + MODIFY_REG(heth->Instance->MACIVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) | + ((uint32_t)pVlanConfig->SVLANType << 19) | + pVlanConfig->VLANTagControl)); + /* Enable Double VLAN processing */ + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP); + } + else + { + MODIFY_REG(heth->Instance->MACVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) | + ((uint32_t)pVlanConfig->SVLANType << 19) | + pVlanConfig->VLANTagControl)); + } + + return HAL_OK; +} + +/** + * @brief Set the VLAN Tag Identifier for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param VLANIdentifier: VLAN Identifier 16 bit value + * @retval None + */ +void HAL_ETHEx_SetTxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t VLANTag, uint32_t VLANIdentifier) +{ + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + MODIFY_REG(heth->Instance->MACIVIR, ETH_MACVIR_VLT, VLANIdentifier); + } + else + { + MODIFY_REG(heth->Instance->MACVIR, ETH_MACVIR_VLT, VLANIdentifier); + } +} + +/** + * @brief Enables the VLAN Tag Filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_EnableVLANProcessing(ETH_HandleTypeDef *heth) +{ + /* Enable VLAN processing */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE); +} + +/** + * @brief Disables the VLAN Tag Filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_DisableVLANProcessing(ETH_HandleTypeDef *heth) +{ + /* Disable VLAN processing */ + CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE); +} + +/** + * @brief Enters the Low Power Idle (LPI) mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param TxAutomate: Enable/Disable automate enter/exit LPI mode. + * @param TxClockStop: Enable/Disable Tx clock stop in LPI mode. + * @retval None + */ +void HAL_ETHEx_EnterLPIMode(ETH_HandleTypeDef *heth, FunctionalState TxAutomate, FunctionalState TxClockStop) +{ + /* Enable LPI Interrupts */ + __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_LPIIE); + + /* Write to LPI Control register: Enter low power mode */ + MODIFY_REG(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE), + (((uint32_t)TxAutomate << 19) | + ((uint32_t)TxClockStop << 21) | + ETH_MACLCSR_LPIEN)); +} + +/** + * @brief Exits the Low Power Idle (LPI) mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETHEx_ExitLPIMode(ETH_HandleTypeDef *heth) +{ + /* Clear the LPI Config and exit low power mode */ + CLEAR_BIT(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE)); + + /* Enable LPI Interrupts */ + __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_LPIIE); +} + +/** + * @brief Returns the ETH MAC LPI event + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event + */ +uint32_t HAL_ETHEx_GetMACLPIEvent(const ETH_HandleTypeDef *heth) +{ + return heth->MACLPIEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.h b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.h new file mode 100644 index 0000000000..397ec092fc --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H5/stm32h5xx_hal_eth_ex.h @@ -0,0 +1,366 @@ +/** + ****************************************************************************** + * @file stm32h5xx_hal_eth_ex.h + * @author MCD Application Team + * @brief Header file of ETH HAL Extended module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2023 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H5xx_HAL_ETH_EX_H +#define STM32H5xx_HAL_ETH_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ETH) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h5xx_hal_def.h" + +/** @addtogroup STM32H5xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETHEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Types ETHEx Exported Types + * @{ + */ + +/** + * @brief ETH RX VLAN structure definition + */ +typedef struct +{ + FunctionalState InnerVLANTagInStatus; /*!< Enables or disables Inner VLAN Tag in Rx Status */ + + uint32_t StripInnerVLANTag; /*!< Sets the Inner VLAN Tag Stripping on Receive + This parameter can be a value of + @ref ETHEx_Rx_Inner_VLAN_Tag_Stripping */ + + FunctionalState InnerVLANTag; /*!< Enables or disables Inner VLAN Tag */ + + FunctionalState DoubleVLANProcessing; /*!< Enable or Disable double VLAN processing */ + + FunctionalState VLANTagHashTableMatch; /*!< Enable or Disable VLAN Tag Hash Table Match */ + + FunctionalState VLANTagInStatus; /*!< Enable or Disable VLAN Tag in Rx status */ + + uint32_t StripVLANTag; /*!< Set the VLAN Tag Stripping on Receive + This parameter can be a value of @ref ETHEx_Rx_VLAN_Tag_Stripping */ + + uint32_t VLANTypeCheck; /*!< Enable or Disable VLAN Type Check + This parameter can be a value of @ref ETHEx_VLAN_Type_Check */ + + FunctionalState VLANTagInverceMatch; /*!< Enable or disable VLAN Tag Inverse Match */ +} ETH_RxVLANConfigTypeDef; +/** + * + */ + +/** + * @brief ETH TX VLAN structure definition + */ +typedef struct +{ + FunctionalState SourceTxDesc; /*!< Enable or Disable VLAN tag source from DMA tx descriptors */ + + FunctionalState SVLANType; /*!< Enable or Disable insertion of SVLAN type */ + + uint32_t VLANTagControl; /*!< Sets the VLAN tag control in tx packets + This parameter can be a value of @ref ETHEx_VLAN_Tag_Control */ +} ETH_TxVLANConfigTypeDef; +/** + * + */ + +/** + * @brief ETH L3 filter structure definition + */ +typedef struct +{ + uint32_t Protocol; /*!< Sets the L3 filter protocol to IPv4 or IPv6 + This parameter can be a value of @ref ETHEx_L3_Protocol */ + + uint32_t SrcAddrFilterMatch; /*!< Sets the L3 filter source address match + This parameter can be a value of @ref ETHEx_L3_Source_Match */ + + uint32_t DestAddrFilterMatch; /*!< Sets the L3 filter destination address match + This parameter can be a value of @ref ETHEx_L3_Destination_Match */ + + uint32_t SrcAddrHigherBitsMatch; /*!< Sets the L3 filter source address higher bits match + This parameter can be a value from 0 to 31 */ + + uint32_t DestAddrHigherBitsMatch; /*!< Sets the L3 filter destination address higher bits match + This parameter can be a value from 0 to 31 */ + + uint32_t Ip4SrcAddr; /*!< Sets the L3 filter IPv4 source address if IPv4 protocol is used + This parameter can be a value from 0x0 to 0xFFFFFFFF */ + + uint32_t Ip4DestAddr; /*!< Sets the L3 filter IPv4 destination address if IPv4 protocol is used + This parameter can be a value from 0 to 0xFFFFFFFF */ + + uint32_t Ip6Addr[4]; /*!< Sets the L3 filter IPv6 address if IPv6 protocol is used + This parameter must be a table of 4 words (4* 32 bits) */ +} ETH_L3FilterConfigTypeDef; +/** + * + */ + +/** + * @brief ETH L4 filter structure definition + */ +typedef struct +{ + uint32_t Protocol; /*!< Sets the L4 filter protocol to TCP or UDP + This parameter can be a value of @ref ETHEx_L4_Protocol */ + + uint32_t SrcPortFilterMatch; /*!< Sets the L4 filter source port match + This parameter can be a value of @ref ETHEx_L4_Source_Match */ + + uint32_t DestPortFilterMatch; /*!< Sets the L4 filter destination port match + This parameter can be a value of @ref ETHEx_L4_Destination_Match */ + + uint32_t SourcePort; /*!< Sets the L4 filter source port + This parameter must be a value from 0x0 to 0xFFFF */ + + uint32_t DestinationPort; /*!< Sets the L4 filter destination port + This parameter must be a value from 0x0 to 0xFFFF */ +} ETH_L4FilterConfigTypeDef; +/** + * + */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Constants ETHEx Exported Constants + * @{ + */ + +/** @defgroup ETHEx_LPI_Event ETHEx LPI Event + * @{ + */ +#define ETH_TX_LPI_ENTRY ETH_MACLCSR_TLPIEN +#define ETH_TX_LPI_EXIT ETH_MACLCSR_TLPIEX +#define ETH_RX_LPI_ENTRY ETH_MACLCSR_RLPIEN +#define ETH_RX_LPI_EXIT ETH_MACLCSR_RLPIEX +/** + * @} + */ + +/** @defgroup ETHEx_L3_Filter ETHEx L3 Filter + * @{ + */ +#define ETH_L3_FILTER_0 0x00000000U +#define ETH_L3_FILTER_1 0x0000000CU +/** + * @} + */ + +/** @defgroup ETHEx_L4_Filter ETHEx L4 Filter + * @{ + */ +#define ETH_L4_FILTER_0 0x00000000U +#define ETH_L4_FILTER_1 0x0000000CU +/** + * @} + */ + +/** @defgroup ETHEx_L3_Protocol ETHEx L3 Protocol + * @{ + */ +#define ETH_L3_IPV6_MATCH ETH_MACL3L4CR_L3PEN +#define ETH_L3_IPV4_MATCH 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L3_Source_Match ETHEx L3 Source Match + * @{ + */ +#define ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L3SAM +#define ETH_L3_SRC_ADDR_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L3SAM | ETH_MACL3L4CR_L3SAIM) +#define ETH_L3_SRC_ADDR_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L3_Destination_Match ETHEx L3 Destination Match + * @{ + */ +#define ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L3DAM +#define ETH_L3_DEST_ADDR_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L3DAM | ETH_MACL3L4CR_L3DAIM) +#define ETH_L3_DEST_ADDR_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Protocol ETHEx L4 Protocol + * @{ + */ +#define ETH_L4_UDP_MATCH ETH_MACL3L4CR_L4PEN +#define ETH_L4_TCP_MATCH 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Source_Match ETHEx L4 Source Match + * @{ + */ +#define ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L4SPM +#define ETH_L4_SRC_PORT_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L4SPM |ETH_MACL3L4CR_L4SPIM) +#define ETH_L4_SRC_PORT_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Destination_Match ETHEx L4 Destination Match + * @{ + */ +#define ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L4DPM +#define ETH_L4_DEST_PORT_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM) +#define ETH_L4_DEST_PORT_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_Rx_Inner_VLAN_Tag_Stripping ETHEx Rx Inner VLAN Tag Stripping + * @{ + */ +#define ETH_INNERVLANTAGRXSTRIPPING_NONE ETH_MACVTR_EIVLS_DONOTSTRIP +#define ETH_INNERVLANTAGRXSTRIPPING_IFPASS ETH_MACVTR_EIVLS_STRIPIFPASS +#define ETH_INNERVLANTAGRXSTRIPPING_IFFAILS ETH_MACVTR_EIVLS_STRIPIFFAILS +#define ETH_INNERVLANTAGRXSTRIPPING_ALWAYS ETH_MACVTR_EIVLS_ALWAYSSTRIP +/** + * @} + */ + +/** @defgroup ETHEx_Rx_VLAN_Tag_Stripping ETHEx Rx VLAN Tag Stripping + * @{ + */ +#define ETH_VLANTAGRXSTRIPPING_NONE ETH_MACVTR_EVLS_DONOTSTRIP +#define ETH_VLANTAGRXSTRIPPING_IFPASS ETH_MACVTR_EVLS_STRIPIFPASS +#define ETH_VLANTAGRXSTRIPPING_IFFAILS ETH_MACVTR_EVLS_STRIPIFFAILS +#define ETH_VLANTAGRXSTRIPPING_ALWAYS ETH_MACVTR_EVLS_ALWAYSSTRIP +/** + * @} + */ + +/** @defgroup ETHEx_VLAN_Type_Check ETHEx VLAN Type Check + * @{ + */ +#define ETH_VLANTYPECHECK_DISABLE ETH_MACVTR_DOVLTC +#define ETH_VLANTYPECHECK_SVLAN (ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL) +#define ETH_VLANTYPECHECK_CVLAN 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_VLAN_Tag_Control ETHEx_VLAN_Tag_Control + * @{ + */ +#define ETH_VLANTAGCONTROL_NONE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_NOVLANTAG) +#define ETH_VLANTAGCONTROL_DELETE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGDELETE) +#define ETH_VLANTAGCONTROL_INSERT (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGINSERT) +#define ETH_VLANTAGCONTROL_REPLACE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGREPLACE) +/** + * @} + */ + +/** @defgroup ETHEx_Tx_VLAN_Tag ETHEx Tx VLAN Tag + * @{ + */ +#define ETH_INNER_TX_VLANTAG 0x00000001U +#define ETH_OUTER_TX_VLANTAG 0x00000000U +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup ETHEx_Exported_Functions + * @{ + */ + +/** @addtogroup ETHEx_Exported_Functions_Group1 + * @{ + */ +/* MAC ARP Offloading APIs ***************************************************/ +void HAL_ETHEx_EnableARPOffload(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableARPOffload(ETH_HandleTypeDef *heth); +void HAL_ETHEx_SetARPAddressMatch(ETH_HandleTypeDef *heth, uint32_t IpAddress); + +/* MAC L3 L4 Filtering APIs ***************************************************/ +void HAL_ETHEx_EnableL3L4Filtering(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableL3L4Filtering(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETHEx_GetL3FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L3FilterConfigTypeDef *pL3FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_GetL4FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L4FilterConfigTypeDef *pL4FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_SetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L3FilterConfigTypeDef *pL3FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_SetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L4FilterConfigTypeDef *pL4FilterConfig); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETHEx_EnableVLANProcessing(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableVLANProcessing(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETHEx_GetRxVLANConfig(const ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig); +HAL_StatusTypeDef HAL_ETHEx_SetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig); +void HAL_ETHEx_SetVLANHashTable(ETH_HandleTypeDef *heth, uint32_t VLANHashTable); +HAL_StatusTypeDef HAL_ETHEx_GetTxVLANConfig(const ETH_HandleTypeDef *heth, uint32_t VLANTag, + ETH_TxVLANConfigTypeDef *pVlanConfig); +HAL_StatusTypeDef HAL_ETHEx_SetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag, + const ETH_TxVLANConfigTypeDef *pVlanConfig); +void HAL_ETHEx_SetTxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t VLANTag, uint32_t VLANIdentifier); + +/* Energy Efficient Ethernet APIs *********************************************/ +void HAL_ETHEx_EnterLPIMode(ETH_HandleTypeDef *heth, FunctionalState TxAutomate, + FunctionalState TxClockStop); +void HAL_ETHEx_ExitLPIMode(ETH_HandleTypeDef *heth); +uint32_t HAL_ETHEx_GetMACLPIEvent(const ETH_HandleTypeDef *heth); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H5xx_HAL_ETH_EX_H */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.c b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.c new file mode 100644 index 0000000000..2536a73b12 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.c @@ -0,0 +1,3379 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_eth.c + * @author MCD Application Team + * @brief ETH HAL module driver. + * This file provides firmware functions to manage the following + * functionalities of the Ethernet (ETH) peripheral: + * + Initialization and deinitialization functions + * + IO operation functions + * + Peripheral Control functions + * + Peripheral State and Errors functions + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + @verbatim + ============================================================================== + ##### How to use this driver ##### + ============================================================================== + [..] + The ETH HAL driver can be used as follows: + + (#)Declare a ETH_HandleTypeDef handle structure, for example: + ETH_HandleTypeDef heth; + + (#)Fill parameters of Init structure in heth handle + + (#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...) + + (#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API: + (##) Enable the Ethernet interface clock using + (+++) __HAL_RCC_ETH1MAC_CLK_ENABLE() + (+++) __HAL_RCC_ETH1TX_CLK_ENABLE() + (+++) __HAL_RCC_ETH1RX_CLK_ENABLE() + + (##) Initialize the related GPIO clocks + (##) Configure Ethernet pinout + (##) Configure Ethernet NVIC interrupt (in Interrupt mode) + + (#) Ethernet data reception is asynchronous, so call the following API + to start the listening mode: + (##) HAL_ETH_Start(): + This API starts the MAC and DMA transmission and reception process, + without enabling end of transfer interrupts, in this mode user + has to poll for data reception by calling HAL_ETH_ReadData() + (##) HAL_ETH_Start_IT(): + This API starts the MAC and DMA transmission and reception process, + end of transfer interrupts are enabled in this mode, + HAL_ETH_RxCpltCallback() will be executed when an Ethernet packet is received + + (#) When data is received user can call the following API to get received data: + (##) HAL_ETH_ReadData(): Read a received packet + + (#) For transmission path, two APIs are available: + (##) HAL_ETH_Transmit(): Transmit an ETH frame in blocking mode + (##) HAL_ETH_Transmit_IT(): Transmit an ETH frame in interrupt mode, + HAL_ETH_TxCpltCallback() will be executed when end of transfer occur + + (#) Communication with an external PHY device: + (##) HAL_ETH_ReadPHYRegister(): Read a register from an external PHY + (##) HAL_ETH_WritePHYRegister(): Write data to an external RHY register + + (#) Configure the Ethernet MAC after ETH peripheral initialization + (##) HAL_ETH_GetMACConfig(): Get MAC actual configuration into ETH_MACConfigTypeDef + (##) HAL_ETH_SetMACConfig(): Set MAC configuration based on ETH_MACConfigTypeDef + + (#) Configure the Ethernet DMA after ETH peripheral initialization + (##) HAL_ETH_GetDMAConfig(): Get DMA actual configuration into ETH_DMAConfigTypeDef + (##) HAL_ETH_SetDMAConfig(): Set DMA configuration based on ETH_DMAConfigTypeDef + + (#) Configure the Ethernet PTP after ETH peripheral initialization + (##) Define HAL_ETH_USE_PTP to use PTP APIs. + (##) HAL_ETH_PTP_GetConfig(): Get PTP actual configuration into ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_SetConfig(): Set PTP configuration based on ETH_PTP_ConfigTypeDef + (##) HAL_ETH_PTP_GetTime(): Get Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_SetTime(): Set Seconds and Nanoseconds for the Ethernet PTP registers + (##) HAL_ETH_PTP_AddTimeOffset(): Add Seconds and Nanoseconds offset for the Ethernet PTP registers + (##) HAL_ETH_PTP_InsertTxTimestamp(): Insert Timestamp in transmission + (##) HAL_ETH_PTP_GetTxTimestamp(): Get transmission timestamp + (##) HAL_ETH_PTP_GetRxTimestamp(): Get reception timestamp + + -@- The ARP offload feature is not supported in this driver. + + -@- The PTP offload feature is not supported in this driver. + + *** Callback registration *** + ============================================= + + The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1 + allows the user to configure dynamically the driver callbacks. + Use Function HAL_ETH_RegisterCallback() to register an interrupt callback. + + Function HAL_ETH_RegisterCallback() allows to register following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + This function takes as parameters the HAL peripheral handle, the Callback ID + and a pointer to the user callback function. + + For specific callbacks RxAllocateCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated register callbacks: + respectively HAL_ETH_RegisterTxPtpCallback(). + + Use function HAL_ETH_UnRegisterCallback() to reset a callback to the default + weak function. + HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle, + and the Callback ID. + This function allows to reset following callbacks: + (+) TxCpltCallback : Tx Complete Callback. + (+) RxCpltCallback : Rx Complete Callback. + (+) ErrorCallback : Error Callback. + (+) PMTCallback : Power Management Callback + (+) EEECallback : EEE Callback. + (+) WakeUpCallback : Wake UP Callback + (+) MspInitCallback : MspInit Callback. + (+) MspDeInitCallback: MspDeInit Callback. + + For specific callbacks RxAllocateCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxAllocateCallback(). + + For specific callbacks RxLinkCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterRxLinkCallback(). + + For specific callbacks TxFreeCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxFreeCallback(). + + For specific callbacks TxPtpCallback use dedicated unregister callbacks: + respectively HAL_ETH_UnRegisterTxPtpCallback(). + + By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET + all callbacks are set to the corresponding weak functions: + examples HAL_ETH_TxCpltCallback(), HAL_ETH_RxCpltCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the HAL_ETH_Init/ HAL_ETH_DeInit only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ HAL_ETH_DeInit + keep and use the user MspInit/MspDeInit callbacks (registered beforehand) + + Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only. + Exception done MspInit/MspDeInit that can be registered/unregistered + in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state, + thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. + In that case first register the MspInit/MspDeInit user callbacks + using HAL_ETH_RegisterCallback() before calling HAL_ETH_DeInit + or HAL_ETH_Init function. + + When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or + not defined, the callback registration feature is not available and all callbacks + are set to the corresponding weak functions. + + @endverbatim + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETH ETH + * @brief ETH HAL module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @addtogroup ETH_Private_Constants ETH Private Constants + * @{ + */ +#define ETH_MACCR_MASK 0xFFFB7F7CU +#define ETH_MACECR_MASK 0x3F077FFFU +#define ETH_MACPFR_MASK 0x800007FFU +#define ETH_MACWTR_MASK 0x0000010FU +#define ETH_MACTFCR_MASK 0xFFFF00F2U +#define ETH_MACRFCR_MASK 0x00000003U +#define ETH_MTLTQOMR_MASK 0x00000072U +#define ETH_MTLRQOMR_MASK 0x0000007BU + +#define ETH_DMAMR_MASK 0x00007802U +#define ETH_DMASBMR_MASK 0x0000D001U +#define ETH_DMACCR_MASK 0x00013FFFU +#define ETH_DMACTCR_MASK 0x003F1010U +#define ETH_DMACRCR_MASK 0x803F0000U +#define ETH_MACPCSR_MASK (ETH_MACPCSR_PWRDWN | ETH_MACPCSR_RWKPKTEN | \ + ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | \ + ETH_MACPCSR_RWKPFE) + +/* Timeout values */ +#define ETH_DMARXNDESCWBF_ERRORS_MASK ((uint32_t)(ETH_DMARXNDESCWBF_DE | ETH_DMARXNDESCWBF_RE | \ + ETH_DMARXNDESCWBF_OE | ETH_DMARXNDESCWBF_RWT |\ + ETH_DMARXNDESCWBF_GP | ETH_DMARXNDESCWBF_CE)) + +#define ETH_MACTSCR_MASK 0x0087FF2FU + +#define ETH_MACSTSUR_VALUE 0xFFFFFFFFU +#define ETH_MACSTNUR_VALUE 0xBB9ACA00U +#define ETH_SEGMENT_SIZE_DEFAULT 0x218U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/** @defgroup ETH_Private_Macros ETH Private Macros + * @{ + */ +/* Helper macros for TX descriptor handling */ +#define INCR_TX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_TX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_TX_DESC_CNT);}\ + } while (0) + +/* Helper macros for RX descriptor handling */ +#define INCR_RX_DESC_INDEX(inx, offset) do {\ + (inx) += (offset);\ + if ((inx) >= (uint32_t)ETH_RX_DESC_CNT){\ + (inx) = ((inx) - (uint32_t)ETH_RX_DESC_CNT);}\ + } while (0) +/** + * @} + */ +/* Private function prototypes -----------------------------------------------*/ +/** @defgroup ETH_Private_Functions ETH Private Functions + * @{ + */ +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf); +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf); +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth); +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth); +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth); +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode); +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ +/** + * @} + */ + +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETH_Exported_Functions ETH Exported Functions + * @{ + */ + +/** @defgroup ETH_Exported_Functions_Group1 Initialization and deinitialization functions + * @brief Initialization and Configuration functions + * +@verbatim +=============================================================================== + ##### Initialization and Configuration functions ##### + =============================================================================== + [..] This subsection provides a set of functions allowing to initialize and + deinitialize the ETH peripheral: + + (+) User must Implement HAL_ETH_MspInit() function in which he configures + all related peripherals resources (CLOCK, GPIO and NVIC ). + + (+) Call the function HAL_ETH_Init() to configure the selected device with + the selected configuration: + (++) MAC address + (++) Media interface (MII or RMII) + (++) Rx DMA Descriptors Tab + (++) Tx DMA Descriptors Tab + (++) Length of Rx Buffers + + (+) Call the function HAL_ETH_DeInit() to restore the default configuration + of the selected ETH peripheral. + +@endverbatim + * @{ + */ + +/** + * @brief Initialize the Ethernet peripheral registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth) +{ + uint32_t tickstart; + + if (heth == NULL) + { + return HAL_ERROR; + } + if (heth->gState == HAL_ETH_STATE_RESET) + { + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + ETH_InitCallbacksToDefault(heth); + + if (heth->MspInitCallback == NULL) + { + heth->MspInitCallback = HAL_ETH_MspInit; + } + + /* Init the low level hardware */ + heth->MspInitCallback(heth); +#else + /* Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + } + + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + if (heth->Init.MediaInterface == HAL_ETH_MII_MODE) + { + HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_MII); + } + else + { + HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RMII); + } + + /* Dummy read to sync with ETH */ + (void)SYSCFG->PMCR; + + /* Ethernet Software reset */ + /* Set the SWR bit: resets all MAC subsystem internal registers and logic */ + /* After reset all the registers holds their respective reset values */ + SET_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR); + + /* Get tick */ + tickstart = HAL_GetTick(); + + /* Wait for software reset */ + while (READ_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + } + + /*------------------ MDIO CSR Clock Range Configuration --------------------*/ + HAL_ETH_SetMDIOClockRange(heth); + + /*------------------ MAC LPI 1US Tic Counter Configuration --------------------*/ + WRITE_REG(heth->Instance->MAC1USTCR, (((uint32_t)HAL_RCC_GetHCLKFreq() / ETH_MAC_US_TICK) - 1U)); + + /*------------------ MAC, MTL and DMA default Configuration ----------------*/ + ETH_MACDMAConfig(heth); + + /* SET DSL to 64 bit */ + MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_DSL, ETH_DMACCR_DSL_64BIT); + + /* Set Receive Buffers Length (must be a multiple of 4) */ + if ((heth->Init.RxBuffLen % 0x4U) != 0x0U) + { + /* Set Error Code */ + heth->ErrorCode = HAL_ETH_ERROR_PARAM; + /* Set State as Error */ + heth->gState = HAL_ETH_STATE_ERROR; + /* Return Error */ + return HAL_ERROR; + } + else + { + MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_RBSZ, ((heth->Init.RxBuffLen) << 1)); + } + + /*------------------ DMA Tx Descriptors Configuration ----------------------*/ + ETH_DMATxDescListInit(heth); + + /*------------------ DMA Rx Descriptors Configuration ----------------------*/ + ETH_DMARxDescListInit(heth); + + /*--------------------- ETHERNET MAC Address Configuration ------------------*/ + /* Set MAC addr bits 32 to 47 */ + heth->Instance->MACA0HR = (((uint32_t)(heth->Init.MACAddr[5]) << 8) | (uint32_t)heth->Init.MACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + heth->Instance->MACA0LR = (((uint32_t)(heth->Init.MACAddr[3]) << 24) | ((uint32_t)(heth->Init.MACAddr[2]) << 16) | + ((uint32_t)(heth->Init.MACAddr[1]) << 8) | (uint32_t)heth->Init.MACAddr[0]); + + /* Disable Rx MMC Interrupts */ + SET_BIT(heth->Instance->MMCRIMR, ETH_MMCRIMR_RXLPITRCIM | ETH_MMCRIMR_RXLPIUSCIM | \ + ETH_MMCRIMR_RXUCGPIM | ETH_MMCRIMR_RXALGNERPIM | ETH_MMCRIMR_RXCRCERPIM); + + /* Disable Tx MMC Interrupts */ + SET_BIT(heth->Instance->MMCTIMR, ETH_MMCTIMR_TXLPITRCIM | ETH_MMCTIMR_TXLPIUSCIM | \ + ETH_MMCTIMR_TXGPKTIM | ETH_MMCTIMR_TXMCOLGPIM | ETH_MMCTIMR_TXSCOLGPIM); + + heth->ErrorCode = HAL_ETH_ERROR_NONE; + heth->gState = HAL_ETH_STATE_READY; + + return HAL_OK; +} + +/** + * @brief DeInitializes the ETH peripheral. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth) +{ + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + + if (heth->MspDeInitCallback == NULL) + { + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + } + /* DeInit the low level hardware */ + heth->MspDeInitCallback(heth); +#else + + /* De-Init the low level hardware : GPIO, CLOCK, NVIC. */ + HAL_ETH_MspDeInit(heth); + +#endif /* (USE_HAL_ETH_REGISTER_CALLBACKS) */ + + /* Set ETH HAL state to Disabled */ + heth->gState = HAL_ETH_STATE_RESET; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Initializes the ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspInit could be implemented in the user file + */ +} + +/** + * @brief DeInitializes ETH MSP. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_MspDeInit could be implemented in the user file + */ +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +/** + * @brief Register a User ETH Callback + * To be used instead of the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be registered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @param pCallback pointer to the Callback function + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (pCallback == NULL) + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = pCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = pCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = pCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = pCallback; + break; + + case HAL_ETH_EEE_CB_ID : + heth->EEECallback = pCallback; + break; + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = pCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = pCallback; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = pCallback; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} + +/** + * @brief Unregister an ETH Callback + * ETH callback is redirected to the weak predefined callback + * @param heth eth handle + * @param CallbackID ID of the callback to be unregistered + * This parameter can be one of the following values: + * @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID + * @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID + * @arg @ref HAL_ETH_ERROR_CB_ID Error Callback ID + * @arg @ref HAL_ETH_PMT_CB_ID Power Management Callback ID + * @arg @ref HAL_ETH_EEE_CB_ID EEE Callback ID + * @arg @ref HAL_ETH_WAKEUP_CB_ID Wake UP Callback ID + * @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID + * @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID + * @retval status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID) +{ + HAL_StatusTypeDef status = HAL_OK; + + if (heth->gState == HAL_ETH_STATE_READY) + { + switch (CallbackID) + { + case HAL_ETH_TX_COMPLETE_CB_ID : + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; + break; + + case HAL_ETH_RX_COMPLETE_CB_ID : + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; + break; + + case HAL_ETH_ERROR_CB_ID : + heth->ErrorCallback = HAL_ETH_ErrorCallback; + break; + + case HAL_ETH_PMT_CB_ID : + heth->PMTCallback = HAL_ETH_PMTCallback; + break; + + case HAL_ETH_EEE_CB_ID : + heth->EEECallback = HAL_ETH_EEECallback; + break; + + case HAL_ETH_WAKEUP_CB_ID : + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; + break; + + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else if (heth->gState == HAL_ETH_STATE_RESET) + { + switch (CallbackID) + { + case HAL_ETH_MSPINIT_CB_ID : + heth->MspInitCallback = HAL_ETH_MspInit; + break; + + case HAL_ETH_MSPDEINIT_CB_ID : + heth->MspDeInitCallback = HAL_ETH_MspDeInit; + break; + + default : + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + break; + } + } + else + { + /* Update the error code */ + heth->ErrorCode |= HAL_ETH_ERROR_INVALID_CALLBACK; + /* Return error status */ + status = HAL_ERROR; + } + + return status; +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group2 IO operation functions + * @brief ETH Transmit and Receive functions + * +@verbatim + ============================================================================== + ##### IO operation functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to manage the ETH + data transfer. + +@endverbatim + * @{ + */ + +/** + * @brief Enables Ethernet MAC and DMA reception and transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Clear Tx and Rx process stopped flags */ + heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS); + + heth->gState = HAL_ETH_STATE_STARTED; + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Enables Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_READY) + { + heth->gState = HAL_ETH_STATE_BUSY; + + /* save IT mode to ETH Handle */ + heth->RxDescList.ItMode = 1U; + + /* Set number of descriptors to build */ + heth->RxDescList.RxBuildDescCnt = ETH_RX_DESC_CNT; + + /* Build all descriptors */ + ETH_UpdateDescriptor(heth); + + /* Enable the DMA transmission */ + SET_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Enable the DMA reception */ + SET_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Clear Tx and Rx process stopped flags */ + heth->Instance->DMACSR |= (ETH_DMACSR_TPS | ETH_DMACSR_RPS); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Enable the MAC transmission */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Enable the MAC reception */ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Enable ETH DMA interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_ENABLE_IT(heth, (ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE | + ETH_DMACIER_FBEE | ETH_DMACIER_AIE | ETH_DMACIER_RBUE)); + + heth->gState = HAL_ETH_STATE_STARTED; + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth) +{ + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Stop Ethernet MAC and DMA reception/transmission in Interrupt mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t descindex; + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Set the ETH peripheral state to BUSY */ + heth->gState = HAL_ETH_STATE_BUSY; + + /* Disable interrupts: + - Tx complete interrupt + - Rx complete interrupt + - Fatal bus interrupt + */ + __HAL_ETH_DMA_DISABLE_IT(heth, (ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE | + ETH_DMACIER_FBEE | ETH_DMACIER_AIE | ETH_DMACIER_RBUE)); + + /* Disable the DMA transmission */ + CLEAR_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_ST); + + /* Disable the DMA reception */ + CLEAR_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_SR); + + /* Disable the MAC reception */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_RE); + + /* Set the Flush Transmit FIFO bit */ + SET_BIT(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_FTQ); + + /* Disable the MAC transmission */ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_TE); + + /* Clear IOC bit to all Rx descriptors */ + for (descindex = 0; descindex < (uint32_t)ETH_RX_DESC_CNT; descindex++) + { + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descindex]; + CLEAR_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCRF_IOC); + } + + heth->RxDescList.ItMode = 0U; + + heth->gState = HAL_ETH_STATE_READY; + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in polling mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @param Timeout: timeout value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout) +{ + uint32_t tickstart; + ETH_DMADescTypeDef *dmatxdesc; + + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 0) != HAL_ETH_ERROR_NONE) + { + /* Set the ETH error code */ + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + dmatxdesc = (ETH_DMADescTypeDef *)(&heth->TxDescList)->TxDesc[heth->TxDescList.CurTxDesc]; + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + tickstart = HAL_GetTick(); + + /* Wait for data to be transmitted or timeout occurred */ + while ((dmatxdesc->DESC3 & ETH_DMATXNDESCWBF_OWN) != (uint32_t)RESET) + { + if ((heth->Instance->DMACSR & ETH_DMACSR_FBE) != (uint32_t)RESET) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + heth->DMAErrorCode = heth->Instance->DMACSR; + /* Return function status */ + return HAL_ERROR; + } + + /* Check for the Timeout */ + if (Timeout != HAL_MAX_DELAY) + { + if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_TIMEOUT; + /* Clear TX descriptor so that we can proceed */ + dmatxdesc->DESC3 = (ETH_DMATXNDESCWBF_FD | ETH_DMATXNDESCWBF_LD); + return HAL_ERROR; + } + } + } + + /* Return function status */ + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Sends an Ethernet Packet in interrupt mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Hold the configuration of packet to be transmitted + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig) +{ + if (pTxConfig == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_STARTED) + { + /* Save the packet pointer to release. */ + heth->TxDescList.CurrentPacketAddress = (uint32_t *)pTxConfig->pData; + + /* Config DMA Tx descriptor by Tx Packet info */ + if (ETH_Prepare_Tx_Descriptors(heth, pTxConfig, 1) != HAL_ETH_ERROR_NONE) + { + heth->ErrorCode |= HAL_ETH_ERROR_BUSY; + return HAL_ERROR; + } + + /* Ensure completion of descriptor preparation before transmission start */ + __DSB(); + + /* Incr current tx desc index */ + INCR_TX_DESC_INDEX(heth->TxDescList.CurTxDesc, 1U); + + /* Start transmission */ + /* issue a poll command to Tx DMA by writing address of next immediate free descriptor */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t)(heth->TxDescList.TxDesc[heth->TxDescList.CurTxDesc])); + + return HAL_OK; + + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Read a received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pAppBuff: Pointer to an application buffer to receive the packet. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff) +{ + uint32_t descidx; + ETH_DMADescTypeDef *dmarxdesc; + uint32_t desccnt = 0U; + uint32_t desccntmax; + uint32_t bufflength; + uint8_t rxdataready = 0U; + + if (pAppBuff == NULL) + { + heth->ErrorCode |= HAL_ETH_ERROR_PARAM; + return HAL_ERROR; + } + + if (heth->gState != HAL_ETH_STATE_STARTED) + { + return HAL_ERROR; + } + + descidx = heth->RxDescList.RxDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccntmax = ETH_RX_DESC_CNT - heth->RxDescList.RxBuildDescCnt; + + /* Check if descriptor is not owned by DMA */ + while ((READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_OWN) == (uint32_t)RESET) && (desccnt < desccntmax) + && (rxdataready == 0U)) + { + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_CTXT) != (uint32_t)RESET) + { + /* Get timestamp high */ + heth->RxDescList.TimeStamp.TimeStampHigh = dmarxdesc->DESC1; + /* Get timestamp low */ + heth->RxDescList.TimeStamp.TimeStampLow = dmarxdesc->DESC0; + } + if ((READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_FD) != (uint32_t)RESET) || (heth->RxDescList.pRxStart != NULL)) + { + /* Check if first descriptor */ + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_FD) != (uint32_t)RESET) + { + heth->RxDescList.RxDescCnt = 0; + heth->RxDescList.RxDataLength = 0; + } + + /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */ + bufflength = READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_PL) - heth->RxDescList.RxDataLength; + + /* Check if last descriptor */ + if (READ_BIT(dmarxdesc->DESC3, ETH_DMARXNDESCWBF_LD) != (uint32_t)RESET) + { + /* Save Last descriptor index */ + heth->RxDescList.pRxLastRxDesc = dmarxdesc->DESC3; + + /* Packet ready */ + rxdataready = 1; + } + + /* Link data */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Link callback*/ + heth->rxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, bufflength); +#else + /* Link callback */ + HAL_ETH_RxLinkCallback(&heth->RxDescList.pRxStart, &heth->RxDescList.pRxEnd, + (uint8_t *)dmarxdesc->BackupAddr0, (uint16_t) bufflength); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->RxDescList.RxDescCnt++; + heth->RxDescList.RxDataLength += bufflength; + + /* Clear buffer pointer */ + dmarxdesc->BackupAddr0 = 0; + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccnt++; + } + + heth->RxDescList.RxBuildDescCnt += desccnt; + if ((heth->RxDescList.RxBuildDescCnt) != 0U) + { + /* Update Descriptors */ + ETH_UpdateDescriptor(heth); + } + + heth->RxDescList.RxDescIdx = descidx; + + if (rxdataready == 1U) + { + /* Return received packet */ + *pAppBuff = heth->RxDescList.pRxStart; + /* Reset first element */ + heth->RxDescList.pRxStart = NULL; + + return HAL_OK; + } + + /* Packet not ready */ + return HAL_ERROR; +} + +/** + * @brief This function gives back Rx Desc of the last received Packet + * to the DMA, so ETH DMA will be able to use these descriptors + * to receive next Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_UpdateDescriptor(ETH_HandleTypeDef *heth) +{ + uint32_t descidx; + uint32_t tailidx; + uint32_t desccount; + ETH_DMADescTypeDef *dmarxdesc; + uint8_t *buff = NULL; + uint8_t allocStatus = 1U; + + descidx = heth->RxDescList.RxBuildDescIdx; + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount = heth->RxDescList.RxBuildDescCnt; + + while ((desccount > 0U) && (allocStatus != 0U)) + { + /* Check if a buffer's attached the descriptor */ + if (READ_REG(dmarxdesc->BackupAddr0) == 0U) + { + /* Get a new buffer. */ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Allocate callback*/ + heth->rxAllocateCallback(&buff); +#else + /* Allocate callback */ + HAL_ETH_RxAllocateCallback(&buff); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + if (buff == NULL) + { + allocStatus = 0U; + } + else + { + WRITE_REG(dmarxdesc->BackupAddr0, (uint32_t)buff); + WRITE_REG(dmarxdesc->DESC0, (uint32_t)buff); + } + } + + if (allocStatus != 0U) + { + + if (heth->RxDescList.ItMode != 0U) + { + WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V | ETH_DMARXNDESCRF_IOC); + } + else + { + WRITE_REG(dmarxdesc->DESC3, ETH_DMARXNDESCRF_OWN | ETH_DMARXNDESCRF_BUF1V); + } + + /* Increment current rx descriptor index */ + INCR_RX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmarxdesc = (ETH_DMADescTypeDef *)heth->RxDescList.RxDesc[descidx]; + desccount--; + } + } + + if (heth->RxDescList.RxBuildDescCnt != desccount) + { + /* Set the tail pointer index */ + tailidx = (descidx + 1U) % ETH_RX_DESC_CNT; + + /* DMB instruction to avoid race condition */ + __DMB(); + + /* Set the Tail pointer address */ + WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (tailidx)))); + + heth->RxDescList.RxBuildDescIdx = descidx; + heth->RxDescList.RxBuildDescCnt = desccount; + } +} + +/** + * @brief Register the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxAllocateCallback: pointer to function to alloc buffer + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback) +{ + if (rxAllocateCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to allocate buffer */ + heth->rxAllocateCallback = rxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx alloc callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; + + return HAL_OK; +} + +/** + * @brief Rx Allocate callback. + * @param buff: pointer to allocated buffer + * @retval None + */ +__weak void HAL_ETH_RxAllocateCallback(uint8_t **buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxAllocateCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Link callback. + * @param pStart: pointer to packet start + * @param pEnd: pointer to packet end + * @param buff: pointer to received data + * @param Length: received data length + * @retval None + */ +__weak void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(pStart); + UNUSED(pEnd); + UNUSED(buff); + UNUSED(Length); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxLinkCallback could be implemented in the user file + */ +} + +/** + * @brief Set the Rx link data function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param rxLinkCallback: pointer to function to link data + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback) +{ + if (rxLinkCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to link data */ + heth->rxLinkCallback = rxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Rx link callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; + + return HAL_OK; +} + +/** + * @brief Get the error state of the last received packet. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pErrorCode: pointer to uint32_t to hold the error code + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode) +{ + /* Get error bits. */ + *pErrorCode = READ_BIT(heth->RxDescList.pRxLastRxDesc, ETH_DMARXNDESCWBF_ERRORS_MASK); + + return HAL_OK; +} + +/** + * @brief Set the Tx free function. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txFreeCallback: pointer to function to release the packet + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback) +{ + if (txFreeCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + + /* Set function to free transmmitted packet */ + heth->txFreeCallback = txFreeCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx free callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; + + return HAL_OK; +} + +/** + * @brief Tx Free callback. + * @param buff: pointer to buffer to free + * @retval None + */ +__weak void HAL_ETH_TxFreeCallback(uint32_t *buff) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxFreeCallback could be implemented in the user file + */ +} + +/** + * @brief Release transmitted Tx packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t numOfBuf = dmatxdesclist->BuffersInUse; + uint32_t idx = dmatxdesclist->releaseIndex; + uint8_t pktTxStatus = 1U; + uint8_t pktInUse; +#ifdef HAL_ETH_USE_PTP + ETH_TimeStampTypeDef *timestamp = &heth->TxTimestamp; +#endif /* HAL_ETH_USE_PTP */ + + /* Loop through buffers in use. */ + while ((numOfBuf != 0U) && (pktTxStatus != 0U)) + { + pktInUse = 1U; + numOfBuf--; + /* If no packet, just examine the next packet. */ + if (dmatxdesclist->PacketAddress[idx] == NULL) + { + /* No packet in use, skip to next. */ + INCR_TX_DESC_INDEX(idx, 1U); + pktInUse = 0U; + } + + if (pktInUse != 0U) + { + /* Determine if the packet has been transmitted. */ + if ((heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCRF_OWN) == 0U) + { +#ifdef HAL_ETH_USE_PTP + + /* Disable Ptp transmission */ + CLEAR_BIT(heth->Init.TxDesc[idx].DESC3, (0x40000000U)); + + if ((heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCWBF_LD) + && (heth->Init.TxDesc[idx].DESC3 & ETH_DMATXNDESCWBF_TTSS)) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->Init.TxDesc[idx].DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->Init.TxDesc[idx].DESC1; + } + else + { + timestamp->TimeStampHigh = timestamp->TimeStampLow = UINT32_MAX; + } +#endif /* HAL_ETH_USE_PTP */ + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered callbacks*/ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + heth->txPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + heth->txFreeCallback(dmatxdesclist->PacketAddress[idx]); +#else + /* Call callbacks */ +#ifdef HAL_ETH_USE_PTP + /* Handle Ptp */ + if (timestamp->TimeStampHigh != UINT32_MAX && timestamp->TimeStampLow != UINT32_MAX) + { + HAL_ETH_TxPtpCallback(dmatxdesclist->PacketAddress[idx], timestamp); + } +#endif /* HAL_ETH_USE_PTP */ + /* Release the packet. */ + HAL_ETH_TxFreeCallback(dmatxdesclist->PacketAddress[idx]); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + /* Clear the entry in the in-use array. */ + dmatxdesclist->PacketAddress[idx] = NULL; + + /* Update the transmit relesae index and number of buffers in use. */ + INCR_TX_DESC_INDEX(idx, 1U); + dmatxdesclist->BuffersInUse = numOfBuf; + dmatxdesclist->releaseIndex = idx; + } + else + { + /* Get out of the loop! */ + pktTxStatus = 0U; + } + } + } + return HAL_OK; +} + +#ifdef HAL_ETH_USE_PTP +/** + * @brief Set the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + uint32_t tmpTSCR; + ETH_TimeTypeDef time; + + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + + tmpTSCR = ptpconfig->Timestamp | + ((uint32_t)ptpconfig->TimestampUpdate << ETH_MACTSCR_TSUPDT_Pos) | + ((uint32_t)ptpconfig->TimestampAll << ETH_MACTSCR_TSENALL_Pos) | + ((uint32_t)ptpconfig->TimestampRolloverMode << ETH_MACTSCR_TSCTRLSSR_Pos) | + ((uint32_t)ptpconfig->TimestampV2 << ETH_MACTSCR_TSVER2ENA_Pos) | + ((uint32_t)ptpconfig->TimestampEthernet << ETH_MACTSCR_TSIPENA_Pos) | + ((uint32_t)ptpconfig->TimestampIPv6 << ETH_MACTSCR_TSIPV6ENA_Pos) | + ((uint32_t)ptpconfig->TimestampIPv4 << ETH_MACTSCR_TSIPV4ENA_Pos) | + ((uint32_t)ptpconfig->TimestampEvent << ETH_MACTSCR_TSEVNTENA_Pos) | + ((uint32_t)ptpconfig->TimestampMaster << ETH_MACTSCR_TSMSTRENA_Pos) | + ((uint32_t)ptpconfig->TimestampSnapshots << ETH_MACTSCR_SNAPTYPSEL_Pos) | + ((uint32_t)ptpconfig->TimestampFilter << ETH_MACTSCR_TSENMACADDR_Pos) | + ((uint32_t)ptpconfig->TimestampChecksumCorrection << ETH_MACTSCR_CSC_Pos) | + ((uint32_t)ptpconfig->TimestampStatusMode << ETH_MACTSCR_TXTSSTSM_Pos); + + /* Write to MACTSCR */ + MODIFY_REG(heth->Instance->MACTSCR, ETH_MACTSCR_MASK, tmpTSCR); + + /* Enable Timestamp */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSENA); + WRITE_REG(heth->Instance->MACSSIR, ptpconfig->TimestampSubsecondInc); + WRITE_REG(heth->Instance->MACTSAR, ptpconfig->TimestampAddend); + + /* Enable Timestamp */ + if (ptpconfig->TimestampAddendUpdate == ENABLE) + { + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSADDREG); + while ((heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG) != 0) + { + + } + } + + /* Ptp Init */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSINIT); + + /* Set PTP Configuration done */ + heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURED; + + /* Set Seconds */ + time.Seconds = heth->Instance->MACSTSR; + /* Set NanoSeconds */ + time.NanoSeconds = heth->Instance->MACSTNR; + + HAL_ETH_PTP_SetTime(heth, &time); + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Get the Ethernet PTP configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ptpconfig: pointer to a ETH_PTP_ConfigTypeDef structure that contains + * the configuration information for PTP + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig) +{ + if (ptpconfig == NULL) + { + return HAL_ERROR; + } + ptpconfig->Timestamp = READ_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSENA); + ptpconfig->TimestampUpdate = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSCFUPDT) >> ETH_MACTSCR_TSUPDT_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampAll = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSENALL) >> ETH_MACTSCR_TSENALL_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampRolloverMode = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSCTRLSSR) >> ETH_MACTSCR_TSCTRLSSR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampV2 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSVER2ENA) >> ETH_MACTSCR_TSVER2ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEthernet = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPENA) >> ETH_MACTSCR_TSIPENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv6 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPV6ENA) >> ETH_MACTSCR_TSIPV6ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampIPv4 = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSIPV4ENA) >> ETH_MACTSCR_TSIPV4ENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampEvent = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSEVNTENA) >> ETH_MACTSCR_TSEVNTENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampMaster = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSMSTRENA) >> ETH_MACTSCR_TSMSTRENA_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampSnapshots = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_SNAPTYPSEL) >> ETH_MACTSCR_SNAPTYPSEL_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampFilter = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TSENMACADDR) >> ETH_MACTSCR_TSENMACADDR_Pos) > 0U) + ? ENABLE : DISABLE; + ptpconfig->TimestampChecksumCorrection = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_CSC) >> ETH_MACTSCR_CSC_Pos) > 0U) ? ENABLE : DISABLE; + ptpconfig->TimestampStatusMode = ((READ_BIT(heth->Instance->MACTSCR, + ETH_MACTSCR_TXTSSTSM) >> ETH_MACTSCR_TXTSSTSM_Pos) > 0U) + ? ENABLE : DISABLE; + + /* Return function status */ + return HAL_OK; +} + +/** + * @brief Set Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to set + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Set Seconds */ + heth->Instance->MACSTSUR = time->Seconds; + + /* Set NanoSeconds */ + heth->Instance->MACSTNUR = time->NanoSeconds; + + /* the system time is updated */ + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSUPDT); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get Seconds and Nanoseconds for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param time: pointer to a ETH_TimeTypeDef structure that contains + * time to get + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get Seconds */ + time->Seconds = heth->Instance->MACSTSR; + /* Get NanoSeconds */ + time->NanoSeconds = heth->Instance->MACSTNR; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Update time for the Ethernet PTP registers. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timeoffset: pointer to a ETH_PtpUpdateTypeDef structure that contains + * the time update information + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + if (ptpoffsettype == HAL_ETH_PTP_NEGATIVE_UPDATE) + { + /* Set Seconds update */ + heth->Instance->MACSTSUR = ETH_MACSTSUR_VALUE - timeoffset->Seconds + 1U; + + if (READ_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSCTRLSSR) == ETH_MACTSCR_TSCTRLSSR) + { + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = ETH_MACSTNUR_VALUE - timeoffset->NanoSeconds; + } + else + { + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = ETH_MACSTSUR_VALUE - timeoffset->NanoSeconds + 1U; + } + } + else + { + /* Set Seconds update */ + heth->Instance->MACSTSUR = timeoffset->Seconds; + /* Set nanoSeconds update */ + heth->Instance->MACSTNUR = timeoffset->NanoSeconds; + } + + SET_BIT(heth->Instance->MACTSCR, ETH_MACTSCR_TSUPDT); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Insert Timestamp in transmission. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Enable Time Stamp transmission */ + SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_TTSE); + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get transmission timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * transmission timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t idx = dmatxdesclist->releaseIndex; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[idx]; + + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = dmatxdesc->DESC0; + /* Get timestamp high */ + timestamp->TimeStampHigh = dmatxdesc->DESC1; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Get receive timestamp. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param timestamp: pointer to ETH_TIMESTAMPTypeDef structure that contains + * receive timestamp + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp) +{ + if (heth->IsPtpConfigured == HAL_ETH_PTP_CONFIGURED) + { + /* Get timestamp low */ + timestamp->TimeStampLow = heth->RxDescList.TimeStamp.TimeStampLow; + /* Get timestamp high */ + timestamp->TimeStampHigh = heth->RxDescList.TimeStamp.TimeStampHigh; + + /* Return function status */ + return HAL_OK; + } + else + { + /* Return function status */ + return HAL_ERROR; + } +} + +/** + * @brief Register the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param txPtpCallback: Function to handle Ptp transmission + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback) +{ + if (txPtpCallback == NULL) + { + /* No buffer to save */ + return HAL_ERROR; + } + /* Set Function to handle Tx Ptp */ + heth->txPtpCallback = txPtpCallback; + + return HAL_OK; +} + +/** + * @brief Unregister the Tx Ptp callback. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth) +{ + /* Set function to allocate buffer */ + heth->txPtpCallback = HAL_ETH_TxPtpCallback; + + return HAL_OK; +} + +/** + * @brief Tx Ptp callback. + * @param buff: pointer to application buffer + * @param timestamp: pointer to ETH_TimeStampTypeDef structure that contains + * transmission timestamp + * @retval None + */ +__weak void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(buff); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxPtpCallback could be implemented in the user file + */ +} +#endif /* HAL_ETH_USE_PTP */ + +/** + * @brief This function handles ETH interrupt request. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth) +{ + uint32_t mac_flag = READ_REG(heth->Instance->MACISR); + uint32_t dma_flag = READ_REG(heth->Instance->DMACSR); + uint32_t dma_itsource = READ_REG(heth->Instance->DMACIER); + uint32_t exti_d1_flag = READ_REG(EXTI_D1->PR3); +#if defined(DUAL_CORE) + uint32_t exti_d2_flag = READ_REG(EXTI_D2->PR3); +#endif /* DUAL_CORE */ + + /* Packet received */ + if (((dma_flag & ETH_DMACSR_RI) != 0U) && ((dma_itsource & ETH_DMACIER_RIE) != 0U)) + { + /* Clear the Eth DMA Rx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_RI | ETH_DMACSR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Receive complete callback*/ + heth->RxCpltCallback(heth); +#else + /* Receive complete callback */ + HAL_ETH_RxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* Packet transmitted */ + if (((dma_flag & ETH_DMACSR_TI) != 0U) && ((dma_itsource & ETH_DMACIER_TIE) != 0U)) + { + /* Clear the Eth DMA Tx IT pending bits */ + __HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMACSR_TI | ETH_DMACSR_NIS); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /*Call registered Transmit complete callback*/ + heth->TxCpltCallback(heth); +#else + /* Transfer complete callback */ + HAL_ETH_TxCpltCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* ETH DMA Error */ + if (((dma_flag & ETH_DMACSR_AIS) != 0U) && ((dma_itsource & ETH_DMACIER_AIE) != 0U)) + { + heth->ErrorCode |= HAL_ETH_ERROR_DMA; + /* if fatal bus error occurred */ + if ((dma_flag & ETH_DMACSR_FBE) != 0U) + { + /* Get DMA error code */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_FBE | ETH_DMACSR_TPS | ETH_DMACSR_RPS)); + + /* Disable all interrupts */ + __HAL_ETH_DMA_DISABLE_IT(heth, ETH_DMACIER_NIE | ETH_DMACIER_AIE); + + /* Set HAL state to ERROR */ + heth->gState = HAL_ETH_STATE_ERROR; + } + else + { + /* Get DMA error status */ + heth->DMAErrorCode = READ_BIT(heth->Instance->DMACSR, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | + ETH_DMACSR_RBU | ETH_DMACSR_AIS)); + + /* Clear the interrupt summary flag */ + __HAL_ETH_DMA_CLEAR_IT(heth, (ETH_DMACSR_CDE | ETH_DMACSR_ETI | ETH_DMACSR_RWT | + ETH_DMACSR_RBU | ETH_DMACSR_AIS)); + } +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet DMA Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + + /* ETH MAC Error IT */ + if (((mac_flag & ETH_MACIER_RXSTSIE) == ETH_MACIER_RXSTSIE) || \ + ((mac_flag & ETH_MACIER_TXSTSIE) == ETH_MACIER_TXSTSIE)) + { + heth->ErrorCode |= HAL_ETH_ERROR_MAC; + + /* Get MAC Rx Tx status and clear Status register pending bit */ + heth->MACErrorCode = READ_REG(heth->Instance->MACRXTXSR); + + heth->gState = HAL_ETH_STATE_ERROR; + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered Error callback*/ + heth->ErrorCallback(heth); +#else + /* Ethernet Error callback */ + HAL_ETH_ErrorCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + heth->MACErrorCode = (uint32_t)(0x0U); + } + + /* ETH PMT IT */ + if ((mac_flag & ETH_MAC_PMT_IT) != 0U) + { + /* Get MAC Wake-up source and clear the status register pending bit */ + heth->MACWakeUpEvent = READ_BIT(heth->Instance->MACPCSR, (ETH_MACPCSR_RWKPRCVD | ETH_MACPCSR_MGKPRCVD)); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered PMT callback*/ + heth->PMTCallback(heth); +#else + /* Ethernet PMT callback */ + HAL_ETH_PMTCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACWakeUpEvent = (uint32_t)(0x0U); + } + + /* ETH EEE IT */ + if ((mac_flag & ETH_MAC_LPI_IT) != 0U) + { + /* Get MAC LPI interrupt source and clear the status register pending bit */ + heth->MACLPIEvent = READ_BIT(heth->Instance->MACLCSR, 0x0000000FU); + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered EEE callback*/ + heth->EEECallback(heth); +#else + /* Ethernet EEE callback */ + HAL_ETH_EEECallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + + heth->MACLPIEvent = (uint32_t)(0x0U); + } + +#if defined(DUAL_CORE) + if (HAL_GetCurrentCPUID() == CM7_CPUID) + { + /* check ETH WAKEUP exti flag */ + if ((exti_d1_flag & ETH_WAKEUP_EXTI_LINE) != 0U) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } + else + { + /* check ETH WAKEUP exti flag */ + if ((exti_d2_flag & ETH_WAKEUP_EXTI_LINE) != 0U) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTID2_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } + } +#else /* DUAL_CORE not defined */ + /* check ETH WAKEUP exti flag */ + if ((exti_d1_flag & ETH_WAKEUP_EXTI_LINE) != 0U) + { + /* Clear ETH WAKEUP Exti pending bit */ + __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(ETH_WAKEUP_EXTI_LINE); +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) + /* Call registered WakeUp callback*/ + heth->WakeUpCallback(heth); +#else + /* ETH WAKEUP callback */ + HAL_ETH_WakeUpCallback(heth); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + } +#endif /* DUAL_CORE */ +} + +/** + * @brief Tx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_TxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Rx Transfer completed callbacks. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_RxCpltCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet transfer error callbacks + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_ErrorCallback could be implemented in the user file + */ +} + +/** + * @brief Ethernet Power Management module IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_PMTCallback could be implemented in the user file + */ +} + +/** + * @brief Energy Efficient Etherent IT callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_EEECallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_EEECallback could be implemented in the user file + */ +} + +/** + * @brief ETH WAKEUP interrupt callback + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +__weak void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(heth); + /* NOTE : This function Should not be modified, when the callback is needed, + the HAL_ETH_WakeUpCallback could be implemented in the user file + */ +} + +/** + * @brief Read a PHY register + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param pRegValue: parameter to hold read value + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue) +{ + uint32_t tickstart; + uint32_t tmpreg; + + /* Check for the Busy flag */ + if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET) + { + return HAL_ERROR; + } + + /* Get the MACMDIOAR value */ + WRITE_REG(tmpreg, heth->Instance->MACMDIOAR); + + /* Prepare the MDIO Address Register value + - Set the PHY device address + - Set the PHY register address + - Set the read mode + - Set the MII Busy bit */ + + MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_RD); + SET_BIT(tmpreg, ETH_MACMDIOAR_MB); + + /* Write the result value into the MDII Address register */ + WRITE_REG(heth->Instance->MACMDIOAR, tmpreg); + + tickstart = HAL_GetTick(); + + /* Wait for the Busy flag */ + while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT)) + { + return HAL_ERROR; + } + } + + /* Get MACMIIDR value */ + WRITE_REG(*pRegValue, (uint16_t)heth->Instance->MACMDIODR); + + return HAL_OK; +} + +/** + * @brief Writes to a PHY register. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param PHYAddr: PHY port address, must be a value from 0 to 31 + * @param PHYReg: PHY register address, must be a value from 0 to 31 + * @param RegValue: the value to write + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue) +{ + uint32_t tickstart; + uint32_t tmpreg; + + /* Check for the Busy flag */ + if (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) != (uint32_t)RESET) + { + return HAL_ERROR; + } + + /* Get the MACMDIOAR value */ + WRITE_REG(tmpreg, heth->Instance->MACMDIOAR); + + /* Prepare the MDIO Address Register value + - Set the PHY device address + - Set the PHY register address + - Set the write mode + - Set the MII Busy bit */ + + MODIFY_REG(tmpreg, ETH_MACMDIOAR_PA, (PHYAddr << 21)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_RDA, (PHYReg << 16)); + MODIFY_REG(tmpreg, ETH_MACMDIOAR_MOC, ETH_MACMDIOAR_MOC_WR); + SET_BIT(tmpreg, ETH_MACMDIOAR_MB); + + /* Give the value to the MII data register */ + WRITE_REG(ETH->MACMDIODR, (uint16_t)RegValue); + + /* Write the result value into the MII Address register */ + WRITE_REG(ETH->MACMDIOAR, tmpreg); + + tickstart = HAL_GetTick(); + + /* Wait for the Busy flag */ + while (READ_BIT(heth->Instance->MACMDIOAR, ETH_MACMDIOAR_MB) > 0U) + { + if (((HAL_GetTick() - tickstart) > ETH_MDIO_BUS_TIMEOUT)) + { + return HAL_ERROR; + } + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions + * @brief ETH control functions + * +@verbatim + ============================================================================== + ##### Peripheral Control functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to control the ETH + peripheral. + +@endverbatim + * @{ + */ +/** + * @brief Get the configuration of the MAC and MTL subsystems. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that will hold + * the configuration of the MAC. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + /* Get MAC parameters */ + macconf->PreambleLength = READ_BIT(heth->Instance->MACCR, ETH_MACCR_PRELEN); + macconf->DeferralCheck = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DC) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->BackOffLimit = READ_BIT(heth->Instance->MACCR, ETH_MACCR_BL); + macconf->RetryTransmission = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DR) >> 8) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseDuringTransmit = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DCRS) >> 9) > 0U) + ? ENABLE : DISABLE; + macconf->ReceiveOwn = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_DO) >> 10) == 0U) ? ENABLE : DISABLE; + macconf->CarrierSenseBeforeTransmit = ((READ_BIT(heth->Instance->MACCR, + ETH_MACCR_ECRSFD) >> 11) > 0U) ? ENABLE : DISABLE; + macconf->LoopbackMode = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_LM) >> 12) > 0U) ? ENABLE : DISABLE; + macconf->DuplexMode = READ_BIT(heth->Instance->MACCR, ETH_MACCR_DM); + macconf->Speed = READ_BIT(heth->Instance->MACCR, ETH_MACCR_FES); + macconf->JumboPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JE) >> 16) > 0U) ? ENABLE : DISABLE; + macconf->Jabber = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_JD) >> 17) == 0U) ? ENABLE : DISABLE; + macconf->Watchdog = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_WD) >> 19) == 0U) ? ENABLE : DISABLE; + macconf->AutomaticPadCRCStrip = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_ACS) >> 20) > 0U) ? ENABLE : DISABLE; + macconf->CRCStripTypePacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_CST) >> 21) > 0U) ? ENABLE : DISABLE; + macconf->Support2KPacket = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_S2KP) >> 22) > 0U) ? ENABLE : DISABLE; + macconf->GiantPacketSizeLimitControl = ((READ_BIT(heth->Instance->MACCR, + ETH_MACCR_GPSLCE) >> 23) > 0U) ? ENABLE : DISABLE; + macconf->InterPacketGapVal = READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPG); + macconf->ChecksumOffload = ((READ_BIT(heth->Instance->MACCR, ETH_MACCR_IPC) >> 27) > 0U) ? ENABLE : DISABLE; + macconf->SourceAddrControl = READ_BIT(heth->Instance->MACCR, ETH_MACCR_SARC); + + macconf->GiantPacketSizeLimit = READ_BIT(heth->Instance->MACECR, ETH_MACECR_GPSL); + macconf->CRCCheckingRxPackets = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_DCRCC) >> 16) == 0U) ? ENABLE : DISABLE; + macconf->SlowProtocolDetect = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_SPEN) >> 17) > 0U) ? ENABLE : DISABLE; + macconf->UnicastSlowProtocolPacketDetect = ((READ_BIT(heth->Instance->MACECR, + ETH_MACECR_USP) >> 18) > 0U) ? ENABLE : DISABLE; + macconf->ExtendedInterPacketGap = ((READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPGEN) >> 24) > 0U) + ? ENABLE : DISABLE; + macconf->ExtendedInterPacketGapVal = READ_BIT(heth->Instance->MACECR, ETH_MACECR_EIPG) >> 25; + + macconf->ProgrammableWatchdog = ((READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_PWE) >> 8) > 0U) ? ENABLE : DISABLE; + macconf->WatchdogTimeout = READ_BIT(heth->Instance->MACWTR, ETH_MACWTR_WTO); + + macconf->TransmitFlowControl = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_TFE) >> 1) > 0U) ? ENABLE : DISABLE; + macconf->ZeroQuantaPause = ((READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_DZPQ) >> 7) == 0U) ? ENABLE : DISABLE; + macconf->PauseLowThreshold = READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PLT); + macconf->PauseTime = (READ_BIT(heth->Instance->MACTFCR, ETH_MACTFCR_PT) >> 16); + macconf->ReceiveFlowControl = (READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_RFE) > 0U) ? ENABLE : DISABLE; + macconf->UnicastPausePacketDetect = ((READ_BIT(heth->Instance->MACRFCR, ETH_MACRFCR_UP) >> 1) > 0U) + ? ENABLE : DISABLE; + + macconf->TransmitQueueMode = READ_BIT(heth->Instance->MTLTQOMR, (ETH_MTLTQOMR_TTC | ETH_MTLTQOMR_TSF)); + + macconf->ReceiveQueueMode = READ_BIT(heth->Instance->MTLRQOMR, (ETH_MTLRQOMR_RTC | ETH_MTLRQOMR_RSF)); + macconf->ForwardRxUndersizedGoodPacket = ((READ_BIT(heth->Instance->MTLRQOMR, + ETH_MTLRQOMR_FUP) >> 3) > 0U) ? ENABLE : DISABLE; + macconf->ForwardRxErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_FEP) >> 4) > 0U) ? ENABLE : DISABLE; + macconf->DropTCPIPChecksumErrorPacket = ((READ_BIT(heth->Instance->MTLRQOMR, + ETH_MTLRQOMR_DISTCPEF) >> 6) == 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Get the configuration of the DMA. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + dmaconf->AddressAlignedBeats = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_AAL) >> 12) > 0U) ? ENABLE : DISABLE; + dmaconf->BurstMode = READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_FB | ETH_DMASBMR_MB); + dmaconf->RebuildINCRxBurst = ((READ_BIT(heth->Instance->DMASBMR, ETH_DMASBMR_RB) >> 15) > 0U) ? ENABLE : DISABLE; + + dmaconf->DMAArbitration = READ_BIT(heth->Instance->DMAMR, (ETH_DMAMR_TXPR | ETH_DMAMR_PR | ETH_DMAMR_DA)); + + dmaconf->PBLx8Mode = ((READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_8PBL) >> 16) > 0U) ? ENABLE : DISABLE; + dmaconf->MaximumSegmentSize = READ_BIT(heth->Instance->DMACCR, ETH_DMACCR_MSS); + + dmaconf->FlushRxPacket = ((READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPF) >> 31) > 0U) ? ENABLE : DISABLE; + dmaconf->RxDMABurstLength = READ_BIT(heth->Instance->DMACRCR, ETH_DMACRCR_RPBL); + + dmaconf->SecondPacketOperate = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_OSP) >> 4) > 0U) ? ENABLE : DISABLE; + dmaconf->TCPSegmentation = ((READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TSE) >> 12) > 0U) ? ENABLE : DISABLE; + dmaconf->TxDMABurstLength = READ_BIT(heth->Instance->DMACTCR, ETH_DMACTCR_TPBL); + + return HAL_OK; +} + +/** + * @brief Set the MAC configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param macconf: pointer to a ETH_MACConfigTypeDef structure that contains + * the configuration of the MAC. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf) +{ + if (macconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetMACConfig(heth, macconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Set the ETH DMA configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param dmaconf: pointer to a ETH_DMAConfigTypeDef structure that will hold + * the configuration of the ETH DMA. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf) +{ + if (dmaconf == NULL) + { + return HAL_ERROR; + } + + if (heth->gState == HAL_ETH_STATE_READY) + { + ETH_SetDMAConfig(heth, dmaconf); + + return HAL_OK; + } + else + { + return HAL_ERROR; + } +} + +/** + * @brief Configures the Clock range of ETH MDIO interface. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth) +{ + uint32_t hclk; + uint32_t tmpreg; + + /* Get the ETHERNET MACMDIOAR value */ + tmpreg = (heth->Instance)->MACMDIOAR; + + /* Clear CSR Clock Range bits */ + tmpreg &= ~ETH_MACMDIOAR_CR; + + /* Get hclk frequency value */ + hclk = HAL_RCC_GetHCLKFreq(); + + /* Set CR bits depending on hclk value */ + if (hclk < 35000000U) + { + /* CSR Clock Range between 0-35 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV16; + } + else if (hclk < 60000000U) + { + /* CSR Clock Range between 35-60 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV26; + } + else if (hclk < 100000000U) + { + /* CSR Clock Range between 60-100 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV42; + } + else if (hclk < 150000000U) + { + /* CSR Clock Range between 100-150 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV62; + } + else if (hclk < 250000000U) + { + /* CSR Clock Range between 150-250 MHz */ + tmpreg |= (uint32_t)ETH_MACMDIOAR_CR_DIV102; + } + else /* (hclk >= 250000000U) */ + { + /* CSR Clock >= 250 MHz */ + tmpreg |= (uint32_t)(ETH_MACMDIOAR_CR_DIV124); + } + + /* Configure the CSR Clock Range */ + (heth->Instance)->MACMDIOAR = (uint32_t)tmpreg; +} + +/** + * @brief Set the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that contains + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + uint32_t filterconfig; + + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + filterconfig = ((uint32_t)pFilterConfig->PromiscuousMode | + ((uint32_t)pFilterConfig->HashUnicast << 1) | + ((uint32_t)pFilterConfig->HashMulticast << 2) | + ((uint32_t)pFilterConfig->DestAddrInverseFiltering << 3) | + ((uint32_t)pFilterConfig->PassAllMulticast << 4) | + ((uint32_t)((pFilterConfig->BroadcastFilter == DISABLE) ? 1U : 0U) << 5) | + ((uint32_t)pFilterConfig->SrcAddrInverseFiltering << 8) | + ((uint32_t)pFilterConfig->SrcAddrFiltering << 9) | + ((uint32_t)pFilterConfig->HachOrPerfectFilter << 10) | + ((uint32_t)pFilterConfig->ReceiveAllMode << 31) | + pFilterConfig->ControlPacketsFilter); + + MODIFY_REG(heth->Instance->MACPFR, ETH_MACPFR_MASK, filterconfig); + + return HAL_OK; +} + +/** + * @brief Get the ETH MAC (L2) Filters configuration. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilterConfig: pointer to a ETH_MACFilterConfigTypeDef structure that will hold + * the configuration of the ETH MAC filters. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig) +{ + if (pFilterConfig == NULL) + { + return HAL_ERROR; + } + + pFilterConfig->PromiscuousMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PR)) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashUnicast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HUC) >> 1) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HashMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HMC) >> 2) > 0U) ? ENABLE : DISABLE; + pFilterConfig->DestAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, + ETH_MACPFR_DAIF) >> 3) > 0U) ? ENABLE : DISABLE; + pFilterConfig->PassAllMulticast = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PM) >> 4) > 0U) ? ENABLE : DISABLE; + pFilterConfig->BroadcastFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_DBF) >> 5) == 0U) ? ENABLE : DISABLE; + pFilterConfig->ControlPacketsFilter = READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_PCF); + pFilterConfig->SrcAddrInverseFiltering = ((READ_BIT(heth->Instance->MACPFR, + ETH_MACPFR_SAIF) >> 8) > 0U) ? ENABLE : DISABLE; + pFilterConfig->SrcAddrFiltering = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_SAF) >> 9) > 0U) ? ENABLE : DISABLE; + pFilterConfig->HachOrPerfectFilter = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_HPF) >> 10) > 0U) + ? ENABLE : DISABLE; + pFilterConfig->ReceiveAllMode = ((READ_BIT(heth->Instance->MACPFR, ETH_MACPFR_RA) >> 31) > 0U) ? ENABLE : DISABLE; + + return HAL_OK; +} + +/** + * @brief Set the source MAC Address to be matched. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param AddrNbr: The MAC address to configure + * This parameter must be a value of the following: + * ETH_MAC_ADDRESS1 + * ETH_MAC_ADDRESS2 + * ETH_MAC_ADDRESS3 + * @param pMACAddr: Pointer to MAC address buffer data (6 bytes) + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr) +{ + uint32_t macaddrlr; + uint32_t macaddrhr; + + if (pMACAddr == NULL) + { + return HAL_ERROR; + } + + /* Get mac addr high reg offset */ + macaddrhr = ((uint32_t) &(heth->Instance->MACA0HR) + AddrNbr); + /* Get mac addr low reg offset */ + macaddrlr = ((uint32_t) &(heth->Instance->MACA0LR) + AddrNbr); + + /* Set MAC addr bits 32 to 47 */ + (*(__IO uint32_t *)macaddrhr) = (((uint32_t)(pMACAddr[5]) << 8) | (uint32_t)pMACAddr[4]); + /* Set MAC addr bits 0 to 31 */ + (*(__IO uint32_t *)macaddrlr) = (((uint32_t)(pMACAddr[3]) << 24) | ((uint32_t)(pMACAddr[2]) << 16) | + ((uint32_t)(pMACAddr[1]) << 8) | (uint32_t)pMACAddr[0]); + + /* Enable address and set source address bit */ + (*(__IO uint32_t *)macaddrhr) |= (ETH_MACAHR_SA | ETH_MACAHR_AE); + + return HAL_OK; +} + +/** + * @brief Set the ETH Hash Table Value. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pHashTable: pointer to a table of two 32 bit values, that contains + * the 64 bits of the hash table. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable) +{ + if (pHashTable == NULL) + { + return HAL_ERROR; + } + + heth->Instance->MACHT0R = pHashTable[0]; + heth->Instance->MACHT1R = pHashTable[1]; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Identifier for Rx packets + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param ComparisonBits: 12 or 16 bit comparison mode + must be a value of @ref ETH_VLAN_Tag_Comparison + * @param VLANIdentifier: VLAN Identifier value + * @retval None + */ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, uint32_t VLANIdentifier) +{ + if (ComparisonBits == ETH_VLANTAGCOMPARISON_16BIT) + { + MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL, VLANIdentifier); + CLEAR_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV); + } + else + { + MODIFY_REG(heth->Instance->MACVTR, ETH_MACVTR_VL_VID, VLANIdentifier); + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_ETV); + } +} + +/** + * @brief Enters the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pPowerDownConfig: a pointer to ETH_PowerDownConfigTypeDef structure + * that contains the Power Down configuration + * @retval None. + */ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, const ETH_PowerDownConfigTypeDef *pPowerDownConfig) +{ + uint32_t powerdownconfig; + + powerdownconfig = (((uint32_t)pPowerDownConfig->MagicPacket << 1) | + ((uint32_t)pPowerDownConfig->WakeUpPacket << 2) | + ((uint32_t)pPowerDownConfig->GlobalUnicast << 9) | + ((uint32_t)pPowerDownConfig->WakeUpForward << 10) | + ETH_MACPCSR_PWRDWN); + + /* Enable PMT interrupt */ + __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_PMTIE); + + MODIFY_REG(heth->Instance->MACPCSR, ETH_MACPCSR_MASK, powerdownconfig); +} + +/** + * @brief Exits from the Power down mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth) +{ + /* clear wake up sources */ + CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKPKTEN | ETH_MACPCSR_MGKPKTEN | ETH_MACPCSR_GLBLUCAST | + ETH_MACPCSR_RWKPFE); + + if (READ_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN) != (uint32_t)RESET) + { + /* Exit power down mode */ + CLEAR_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_PWRDWN); + } + + /* Disable PMT interrupt */ + __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_PMTIE); +} + +/** + * @brief Set the WakeUp filter. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pFilter: pointer to filter registers values + * @param Count: number of filter registers, must be from 1 to 8. + * @retval None. + */ +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count) +{ + uint32_t regindex; + + if (pFilter == NULL) + { + return HAL_ERROR; + } + + /* Reset Filter Pointer */ + SET_BIT(heth->Instance->MACPCSR, ETH_MACPCSR_RWKFILTRST); + + /* Wake up packet filter config */ + for (regindex = 0; regindex < Count; regindex++) + { + /* Write filter regs */ + WRITE_REG(heth->Instance->MACRWKPFR, pFilter[regindex]); + } + + return HAL_OK; +} + +/** + * @} + */ + +/** @defgroup ETH_Exported_Functions_Group4 Peripheral State and Errors functions + * @brief ETH State and Errors functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Errors functions ##### + ============================================================================== + [..] + This subsection provides a set of functions allowing to return the State of + ETH communication process, return Peripheral Errors occurred during communication + process + + +@endverbatim + * @{ + */ + +/** + * @brief Returns the ETH state. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL state + */ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth) +{ + return heth->gState; +} + +/** + * @brief Returns the ETH error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH Error Code + */ +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth) +{ + return heth->ErrorCode; +} + +/** + * @brief Returns the ETH DMA error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH DMA Error Code + */ +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth) +{ + return heth->DMAErrorCode; +} + +/** + * @brief Returns the ETH MAC error code + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC Error Code + */ +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth) +{ + return heth->MACErrorCode; +} + +/** + * @brief Returns the ETH MAC WakeUp event source + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event source + */ +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth) +{ + return heth->MACWakeUpEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** @addtogroup ETH_Private_Functions ETH Private Functions + * @{ + */ + +static void ETH_SetMACConfig(ETH_HandleTypeDef *heth, const ETH_MACConfigTypeDef *macconf) +{ + uint32_t macregval; + + /*------------------------ MACCR Configuration --------------------*/ + macregval = (macconf->InterPacketGapVal | + macconf->SourceAddrControl | + ((uint32_t)macconf->ChecksumOffload << 27) | + ((uint32_t)macconf->GiantPacketSizeLimitControl << 23) | + ((uint32_t)macconf->Support2KPacket << 22) | + ((uint32_t)macconf->CRCStripTypePacket << 21) | + ((uint32_t)macconf->AutomaticPadCRCStrip << 20) | + ((uint32_t)((macconf->Watchdog == DISABLE) ? 1U : 0U) << 19) | + ((uint32_t)((macconf->Jabber == DISABLE) ? 1U : 0U) << 17) | + ((uint32_t)macconf->JumboPacket << 16) | + macconf->Speed | + macconf->DuplexMode | + ((uint32_t)macconf->LoopbackMode << 12) | + ((uint32_t)macconf->CarrierSenseBeforeTransmit << 11) | + ((uint32_t)((macconf->ReceiveOwn == DISABLE) ? 1U : 0U) << 10) | + ((uint32_t)macconf->CarrierSenseDuringTransmit << 9) | + ((uint32_t)((macconf->RetryTransmission == DISABLE) ? 1U : 0U) << 8) | + macconf->BackOffLimit | + ((uint32_t)macconf->DeferralCheck << 4) | + macconf->PreambleLength); + + /* Write to MACCR */ + MODIFY_REG(heth->Instance->MACCR, ETH_MACCR_MASK, macregval); + + /*------------------------ MACECR Configuration --------------------*/ + macregval = ((macconf->ExtendedInterPacketGapVal << 25) | + ((uint32_t)macconf->ExtendedInterPacketGap << 24) | + ((uint32_t)macconf->UnicastSlowProtocolPacketDetect << 18) | + ((uint32_t)macconf->SlowProtocolDetect << 17) | + ((uint32_t)((macconf->CRCCheckingRxPackets == DISABLE) ? 1U : 0U) << 16) | + macconf->GiantPacketSizeLimit); + + /* Write to MACECR */ + MODIFY_REG(heth->Instance->MACECR, ETH_MACECR_MASK, macregval); + + /*------------------------ MACWTR Configuration --------------------*/ + macregval = (((uint32_t)macconf->ProgrammableWatchdog << 8) | + macconf->WatchdogTimeout); + + /* Write to MACWTR */ + MODIFY_REG(heth->Instance->MACWTR, ETH_MACWTR_MASK, macregval); + + /*------------------------ MACTFCR Configuration --------------------*/ + macregval = (((uint32_t)macconf->TransmitFlowControl << 1) | + macconf->PauseLowThreshold | + ((uint32_t)((macconf->ZeroQuantaPause == DISABLE) ? 1U : 0U) << 7) | + (macconf->PauseTime << 16)); + + /* Write to MACTFCR */ + MODIFY_REG(heth->Instance->MACTFCR, ETH_MACTFCR_MASK, macregval); + + /*------------------------ MACRFCR Configuration --------------------*/ + macregval = ((uint32_t)macconf->ReceiveFlowControl | + ((uint32_t)macconf->UnicastPausePacketDetect << 1)); + + /* Write to MACRFCR */ + MODIFY_REG(heth->Instance->MACRFCR, ETH_MACRFCR_MASK, macregval); + + /*------------------------ MTLTQOMR Configuration --------------------*/ + /* Write to MTLTQOMR */ + MODIFY_REG(heth->Instance->MTLTQOMR, ETH_MTLTQOMR_MASK, macconf->TransmitQueueMode); + + /*------------------------ MTLRQOMR Configuration --------------------*/ + macregval = (macconf->ReceiveQueueMode | + ((uint32_t)((macconf->DropTCPIPChecksumErrorPacket == DISABLE) ? 1U : 0U) << 6) | + ((uint32_t)macconf->ForwardRxErrorPacket << 4) | + ((uint32_t)macconf->ForwardRxUndersizedGoodPacket << 3)); + + /* Write to MTLRQOMR */ + MODIFY_REG(heth->Instance->MTLRQOMR, ETH_MTLRQOMR_MASK, macregval); +} + +static void ETH_SetDMAConfig(ETH_HandleTypeDef *heth, const ETH_DMAConfigTypeDef *dmaconf) +{ + uint32_t dmaregval; + + /*------------------------ DMAMR Configuration --------------------*/ + MODIFY_REG(heth->Instance->DMAMR, ETH_DMAMR_MASK, dmaconf->DMAArbitration); + + /*------------------------ DMASBMR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->AddressAlignedBeats << 12) | + dmaconf->BurstMode | + ((uint32_t)dmaconf->RebuildINCRxBurst << 15)); + + MODIFY_REG(heth->Instance->DMASBMR, ETH_DMASBMR_MASK, dmaregval); + + /*------------------------ DMACCR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->PBLx8Mode << 16) | + dmaconf->MaximumSegmentSize); + MODIFY_REG(heth->Instance->DMACCR, ETH_DMACCR_MASK, dmaregval); + + /*------------------------ DMACTCR Configuration --------------------*/ + dmaregval = (dmaconf->TxDMABurstLength | + ((uint32_t)dmaconf->SecondPacketOperate << 4) | + ((uint32_t)dmaconf->TCPSegmentation << 12)); + + MODIFY_REG(heth->Instance->DMACTCR, ETH_DMACTCR_MASK, dmaregval); + + /*------------------------ DMACRCR Configuration --------------------*/ + dmaregval = (((uint32_t)dmaconf->FlushRxPacket << 31) | + dmaconf->RxDMABurstLength); + + /* Write to DMACRCR */ + MODIFY_REG(heth->Instance->DMACRCR, ETH_DMACRCR_MASK, dmaregval); +} + +/** + * @brief Configures Ethernet MAC and DMA with default parameters. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval HAL status + */ +static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth) +{ + ETH_MACConfigTypeDef macDefaultConf; + ETH_DMAConfigTypeDef dmaDefaultConf; + + /*--------------- ETHERNET MAC registers default Configuration --------------*/ + macDefaultConf.AutomaticPadCRCStrip = ENABLE; + macDefaultConf.BackOffLimit = ETH_BACKOFFLIMIT_10; + macDefaultConf.CarrierSenseBeforeTransmit = DISABLE; + macDefaultConf.CarrierSenseDuringTransmit = DISABLE; + macDefaultConf.ChecksumOffload = ENABLE; + macDefaultConf.CRCCheckingRxPackets = ENABLE; + macDefaultConf.CRCStripTypePacket = ENABLE; + macDefaultConf.DeferralCheck = DISABLE; + macDefaultConf.DropTCPIPChecksumErrorPacket = ENABLE; + macDefaultConf.DuplexMode = ETH_FULLDUPLEX_MODE; + macDefaultConf.ExtendedInterPacketGap = DISABLE; + macDefaultConf.ExtendedInterPacketGapVal = 0x0U; + macDefaultConf.ForwardRxErrorPacket = DISABLE; + macDefaultConf.ForwardRxUndersizedGoodPacket = DISABLE; + macDefaultConf.GiantPacketSizeLimit = 0x618U; + macDefaultConf.GiantPacketSizeLimitControl = DISABLE; + macDefaultConf.InterPacketGapVal = ETH_INTERPACKETGAP_96BIT; + macDefaultConf.Jabber = ENABLE; + macDefaultConf.JumboPacket = DISABLE; + macDefaultConf.LoopbackMode = DISABLE; + macDefaultConf.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS_4; + macDefaultConf.PauseTime = 0x0U; + macDefaultConf.PreambleLength = ETH_PREAMBLELENGTH_7; + macDefaultConf.ProgrammableWatchdog = DISABLE; + macDefaultConf.ReceiveFlowControl = DISABLE; + macDefaultConf.ReceiveOwn = ENABLE; + macDefaultConf.ReceiveQueueMode = ETH_RECEIVESTOREFORWARD; + macDefaultConf.RetryTransmission = ENABLE; + macDefaultConf.SlowProtocolDetect = DISABLE; + macDefaultConf.SourceAddrControl = ETH_SOURCEADDRESS_REPLACE_ADDR0; + macDefaultConf.Speed = ETH_SPEED_100M; + macDefaultConf.Support2KPacket = DISABLE; + macDefaultConf.TransmitQueueMode = ETH_TRANSMITSTOREFORWARD; + macDefaultConf.TransmitFlowControl = DISABLE; + macDefaultConf.UnicastPausePacketDetect = DISABLE; + macDefaultConf.UnicastSlowProtocolPacketDetect = DISABLE; + macDefaultConf.Watchdog = ENABLE; + macDefaultConf.WatchdogTimeout = ETH_MACWTR_WTO_2KB; + macDefaultConf.ZeroQuantaPause = ENABLE; + + /* MAC default configuration */ + ETH_SetMACConfig(heth, &macDefaultConf); + + /*--------------- ETHERNET DMA registers default Configuration --------------*/ + dmaDefaultConf.AddressAlignedBeats = ENABLE; + dmaDefaultConf.BurstMode = ETH_BURSTLENGTH_FIXED; + dmaDefaultConf.DMAArbitration = ETH_DMAARBITRATION_RX1_TX1; + dmaDefaultConf.FlushRxPacket = DISABLE; + dmaDefaultConf.PBLx8Mode = DISABLE; + dmaDefaultConf.RebuildINCRxBurst = DISABLE; + dmaDefaultConf.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.SecondPacketOperate = DISABLE; + dmaDefaultConf.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT; + dmaDefaultConf.TCPSegmentation = DISABLE; + dmaDefaultConf.MaximumSegmentSize = ETH_SEGMENT_SIZE_DEFAULT; + + /* DMA default configuration */ + ETH_SetDMAConfig(heth, &dmaDefaultConf); +} + +/** + * @brief Initializes the DMA Tx descriptors. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMATxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmatxdesc; + uint32_t i; + + /* Fill each DMATxDesc descriptor with the right values */ + for (i = 0; i < (uint32_t)ETH_TX_DESC_CNT; i++) + { + dmatxdesc = heth->Init.TxDesc + i; + + WRITE_REG(dmatxdesc->DESC0, 0x0U); + WRITE_REG(dmatxdesc->DESC1, 0x0U); + WRITE_REG(dmatxdesc->DESC2, 0x0U); + WRITE_REG(dmatxdesc->DESC3, 0x0U); + + WRITE_REG(heth->TxDescList.TxDesc[i], (uint32_t)dmatxdesc); + + } + + heth->TxDescList.CurTxDesc = 0; + + /* Set Transmit Descriptor Ring Length */ + WRITE_REG(heth->Instance->DMACTDRLR, (ETH_TX_DESC_CNT - 1U)); + + /* Set Transmit Descriptor List Address */ + WRITE_REG(heth->Instance->DMACTDLAR, (uint32_t) heth->Init.TxDesc); + + /* Set Transmit Descriptor Tail pointer */ + WRITE_REG(heth->Instance->DMACTDTPR, (uint32_t) heth->Init.TxDesc); +} + +/** + * @brief Initializes the DMA Rx descriptors in chain mode. + * called by HAL_ETH_Init() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +static void ETH_DMARxDescListInit(ETH_HandleTypeDef *heth) +{ + ETH_DMADescTypeDef *dmarxdesc; + uint32_t i; + + for (i = 0; i < (uint32_t)ETH_RX_DESC_CNT; i++) + { + dmarxdesc = heth->Init.RxDesc + i; + + WRITE_REG(dmarxdesc->DESC0, 0x0U); + WRITE_REG(dmarxdesc->DESC1, 0x0U); + WRITE_REG(dmarxdesc->DESC2, 0x0U); + WRITE_REG(dmarxdesc->DESC3, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr0, 0x0U); + WRITE_REG(dmarxdesc->BackupAddr1, 0x0U); + + /* Set Rx descritors addresses */ + WRITE_REG(heth->RxDescList.RxDesc[i], (uint32_t)dmarxdesc); + + } + + WRITE_REG(heth->RxDescList.RxDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxDescCnt, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescIdx, 0U); + WRITE_REG(heth->RxDescList.RxBuildDescCnt, 0U); + WRITE_REG(heth->RxDescList.ItMode, 0U); + + /* Set Receive Descriptor Ring Length */ + WRITE_REG(heth->Instance->DMACRDRLR, ((uint32_t)(ETH_RX_DESC_CNT - 1U))); + + /* Set Receive Descriptor List Address */ + WRITE_REG(heth->Instance->DMACRDLAR, (uint32_t) heth->Init.RxDesc); + + /* Set Receive Descriptor Tail pointer Address */ + WRITE_REG(heth->Instance->DMACRDTPR, ((uint32_t)(heth->Init.RxDesc + (uint32_t)(ETH_RX_DESC_CNT - 1U)))); +} + +/** + * @brief Prepare Tx DMA descriptor before transmission. + * called by HAL_ETH_Transmit_IT and HAL_ETH_Transmit_IT() API. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pTxConfig: Tx packet configuration + * @param ItMode: Enable or disable Tx EOT interrept + * @retval Status + */ +static uint32_t ETH_Prepare_Tx_Descriptors(ETH_HandleTypeDef *heth, const ETH_TxPacketConfigTypeDef *pTxConfig, + uint32_t ItMode) +{ + ETH_TxDescListTypeDef *dmatxdesclist = &heth->TxDescList; + uint32_t descidx = dmatxdesclist->CurTxDesc; + uint32_t firstdescidx = dmatxdesclist->CurTxDesc; + uint32_t idx; + uint32_t descnbr = 0; + ETH_DMADescTypeDef *dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + ETH_BufferTypeDef *txbuffer = pTxConfig->TxBuffer; + uint32_t bd_count = 0; + uint32_t primask_bit; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + return HAL_ETH_ERROR_BUSY; + } + + /***************************************************************************/ + /***************** Context descriptor configuration (Optional) **********/ + /***************************************************************************/ + /* If VLAN tag is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + { + /* Set vlan tag value */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_VT, pTxConfig->VlanTag); + /* Set vlan tag valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_VLTV); + /* Set the descriptor as the vlan input source */ + SET_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI); + + /* if inner VLAN is enabled */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_INNERVLANTAG) != (uint32_t)RESET) + { + /* Set inner vlan tag value */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_IVT, (pTxConfig->InnerVlanTag << 16)); + /* Set inner vlan tag valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_IVLTV); + + /* Set Vlan Tag control */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXCDESC_IVTIR, pTxConfig->InnerVlanCtrl); + + /* Set the descriptor as the inner vlan input source */ + SET_BIT(heth->Instance->MACIVIR, ETH_MACIVIR_VLTI); + /* Enable double VLAN processing */ + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP); + } + } + + /* if tcp segmentation is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set MSS value */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXCDESC_MSS, pTxConfig->MaxSegmentSize); + /* Set MSS valid bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_TCMSSV); + } + + if ((READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + || (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET)) + { + /* Set as context descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_CTXT); + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set own bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN); + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + descnbr += 1U; + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if (READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCWBF_OWN) == ETH_DMATXNDESCWBF_OWN) + { + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[firstdescidx]; + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Clear own bit */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXCDESC_OWN); + + return HAL_ETH_ERROR_BUSY; + } + } + + /***************************************************************************/ + /***************** Normal descriptors configuration *****************/ + /***************************************************************************/ + + descnbr += 1U; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer); + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len); + + if (txbuffer->next != NULL) + { + txbuffer = txbuffer->next; + /* Set buffer 2 address */ + WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16)); + } + else + { + WRITE_REG(dmatxdesc->DESC1, 0x0U); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set TCP Header length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_THL, (pTxConfig->TCPHeaderLen << 19)); + /* Set TCP payload length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen); + /* Set TCP Segmentation Enabled bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE); + } + else + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CRCPAD) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CPC, pTxConfig->CRCPadCtrl); + } + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_VLANTAG) != (uint32_t)RESET) + { + /* Set Vlan Tag control */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_VTIR, pTxConfig->VlanCtrl); + } + + /* Mark it as First Descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD); + /* Mark it as NORMAL descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT); + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* set OWN bit of FIRST descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + + /* If source address insertion/replacement is enabled for this packet */ + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_SAIC) != (uint32_t)RESET) + { + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_SAIC, pTxConfig->SrcAddrCtrl); + } + + /* only if the packet is split into more than one descriptors > 1 */ + while (txbuffer->next != NULL) + { + /* Clear the LD bit of previous descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD); + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* Clear the FD bit of new Descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FD); + + /* Current Tx Descriptor Owned by DMA: cannot be used by the application */ + if ((READ_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN) == ETH_DMATXNDESCRF_OWN) + || (dmatxdesclist->PacketAddress[descidx] != NULL)) + { + descidx = firstdescidx; + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + + /* clear previous desc own bit */ + for (idx = 0; idx < descnbr; idx ++) + { + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + + /* Increment current tx descriptor index */ + INCR_TX_DESC_INDEX(descidx, 1U); + /* Get current descriptor address */ + dmatxdesc = (ETH_DMADescTypeDef *)dmatxdesclist->TxDesc[descidx]; + } + + return HAL_ETH_ERROR_BUSY; + } + + descnbr += 1U; + + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + + /* Set header or buffer 1 address */ + WRITE_REG(dmatxdesc->DESC0, (uint32_t)txbuffer->buffer); + /* Set header or buffer 1 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B1L, txbuffer->len); + + if (txbuffer->next != NULL) + { + /* Get the next Tx buffer in the list */ + txbuffer = txbuffer->next; + /* Set buffer 2 address */ + WRITE_REG(dmatxdesc->DESC1, (uint32_t)txbuffer->buffer); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, (txbuffer->len << 16)); + } + else + { + WRITE_REG(dmatxdesc->DESC1, 0x0U); + /* Set buffer 2 Length */ + MODIFY_REG(dmatxdesc->DESC2, ETH_DMATXNDESCRF_B2L, 0x0U); + } + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_TSO) != (uint32_t)RESET) + { + /* Set TCP payload length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TPL, pTxConfig->PayloadLen); + /* Set TCP Segmentation Enabled bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_TSE); + } + else + { + /* Set the packet length */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_FL, pTxConfig->Length); + + if (READ_BIT(pTxConfig->Attributes, ETH_TX_PACKETS_FEATURES_CSUM) != (uint32_t)RESET) + { + /* Checksum Insertion Control */ + MODIFY_REG(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CIC, pTxConfig->ChecksumCtrl); + } + } + + bd_count += 1U; + + /* Ensure rest of descriptor is written to RAM before the OWN bit */ + __DMB(); + /* Set Own bit */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_OWN); + /* Mark it as NORMAL descriptor */ + CLEAR_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_CTXT); + } + + if (ItMode != ((uint32_t)RESET)) + { + /* Set Interrupt on completion bit */ + SET_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC); + } + else + { + /* Clear Interrupt on completion bit */ + CLEAR_BIT(dmatxdesc->DESC2, ETH_DMATXNDESCRF_IOC); + } + + /* Mark it as LAST descriptor */ + SET_BIT(dmatxdesc->DESC3, ETH_DMATXNDESCRF_LD); + /* Save the current packet address to expose it to the application */ + dmatxdesclist->PacketAddress[descidx] = dmatxdesclist->CurrentPacketAddress; + + dmatxdesclist->CurTxDesc = descidx; + + /* Enter critical section */ + primask_bit = __get_PRIMASK(); + __set_PRIMASK(1); + + dmatxdesclist->BuffersInUse += bd_count + 1U; + + /* Exit critical section: restore previous priority mask */ + __set_PRIMASK(primask_bit); + + /* Return function status */ + return HAL_ETH_ERROR_NONE; +} + +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth) +{ + /* Init the ETH Callback settings */ + heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */ + heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */ + heth->ErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak ErrorCallback */ + heth->PMTCallback = HAL_ETH_PMTCallback; /* Legacy weak PMTCallback */ + heth->EEECallback = HAL_ETH_EEECallback; /* Legacy weak EEECallback */ + heth->WakeUpCallback = HAL_ETH_WakeUpCallback; /* Legacy weak WakeUpCallback */ + heth->rxLinkCallback = HAL_ETH_RxLinkCallback; /* Legacy weak RxLinkCallback */ + heth->txFreeCallback = HAL_ETH_TxFreeCallback; /* Legacy weak TxFreeCallback */ +#ifdef HAL_ETH_USE_PTP + heth->txPtpCallback = HAL_ETH_TxPtpCallback; /* Legacy weak TxPtpCallback */ +#endif /* HAL_ETH_USE_PTP */ + heth->rxAllocateCallback = HAL_ETH_RxAllocateCallback; /* Legacy weak RxAllocateCallback */ +} +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ + +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.h b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.h new file mode 100644 index 0000000000..726127ea68 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth.h @@ -0,0 +1,1849 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_eth.h + * @author MCD Application Team + * @brief Header file of ETH HAL module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_ETH_H +#define STM32H7xx_HAL_ETH_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal_def.h" + +#if defined(ETH) + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETH + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +#ifndef ETH_TX_DESC_CNT +#define ETH_TX_DESC_CNT 4U +#endif /* ETH_TX_DESC_CNT */ + +#ifndef ETH_RX_DESC_CNT +#define ETH_RX_DESC_CNT 4U +#endif /* ETH_RX_DESC_CNT */ + +#ifndef ETH_SWRESET_TIMEOUT +#define ETH_SWRESET_TIMEOUT 500U +#endif /* ETH_SWRESET_TIMEOUT */ + +#ifndef ETH_MDIO_BUS_TIMEOUT +#define ETH_MDIO_BUS_TIMEOUT 1000U +#endif /* ETH_MDIO_BUS_TIMEOUT */ + +#ifndef ETH_MAC_US_TICK +#define ETH_MAC_US_TICK 1000000U +#endif /* ETH_MAC_US_TICK */ + +/*********************** Descriptors struct def section ************************/ +/** @defgroup ETH_Exported_Types ETH Exported Types + * @{ + */ + +/** + * @brief ETH DMA Descriptor structure definition + */ +typedef struct +{ + __IO uint32_t DESC0; + __IO uint32_t DESC1; + __IO uint32_t DESC2; + __IO uint32_t DESC3; + uint32_t BackupAddr0; /* used to store rx buffer 1 address */ + uint32_t BackupAddr1; /* used to store rx buffer 2 address */ +} ETH_DMADescTypeDef; +/** + * + */ + +/** + * @brief ETH Buffers List structure definition + */ +typedef struct __ETH_BufferTypeDef +{ + uint8_t *buffer; /*gState = HAL_ETH_STATE_RESET; \ + (__HANDLE__)->MspInitCallback = NULL; \ + (__HANDLE__)->MspDeInitCallback = NULL; \ + } while(0) +#else +#define __HAL_ETH_RESET_HANDLE_STATE(__HANDLE__) do{ \ + (__HANDLE__)->gState = HAL_ETH_STATE_RESET; \ + } while(0) +#endif /*USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @brief Enables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * enabled @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET DMA interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET DMA interrupt sources to be + * disabled. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACIER &= ~(__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT source enabled or disabled. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The ETH DMA IT Source enabled or disabled + */ +#define __HAL_ETH_DMA_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) \ + (((__HANDLE__)->Instance->DMACIER & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Gets the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt source to get . @ref ETH_DMA_Interrupts + * @retval The state of ETH DMA IT (SET or RESET) + */ +#define __HAL_ETH_DMA_GET_IT(__HANDLE__, __INTERRUPT__) \ + (((__HANDLE__)->Instance->DMACSR & (__INTERRUPT__)) == (__INTERRUPT__)) + +/** + * @brief Clears the ETHERNET DMA IT pending bit. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the interrupt pending bit to clear. @ref ETH_DMA_Interrupts + * @retval None + */ +#define __HAL_ETH_DMA_CLEAR_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DMACSR = (__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET DMA flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->DMACSR &( __FLAG__)) == ( __FLAG__)) + +/** + * @brief Clears the specified ETHERNET DMA flag. + * @param __HANDLE__: ETH Handle + * @param __FLAG__: specifies the flag to check. @ref ETH_DMA_Status_Flags + * @retval The state of ETH DMA FLAG (SET or RESET). + */ +#define __HAL_ETH_DMA_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->DMACSR = ( __FLAG__)) + +/** + * @brief Enables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ + +#define __HAL_ETH_MAC_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER |= (__INTERRUPT__)) + +/** + * @brief Disables the specified ETHERNET MAC interrupts. + * @param __HANDLE__ : ETH Handle + * @param __INTERRUPT__: specifies the ETHERNET MAC interrupt sources to be + * enabled @ref ETH_MAC_Interrupts + * @retval None + */ +#define __HAL_ETH_MAC_DISABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->MACIER &= ~(__INTERRUPT__)) + +/** + * @brief Checks whether the specified ETHERNET MAC flag is set or not. + * @param __HANDLE__: ETH Handle + * @param __INTERRUPT__: specifies the flag to check. @ref ETH_MAC_Interrupts + * @retval The state of ETH MAC IT (SET or RESET). + */ +#define __HAL_ETH_MAC_GET_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->MACISR &\ + ( __INTERRUPT__)) == ( __INTERRUPT__)) + +/*!< External interrupt line 86 Connected to the ETH wakeup EXTI Line */ +#define ETH_WAKEUP_EXTI_LINE 0x00400000U /* !< 86 - 64 = 22 */ + +/** + * @brief Enable the ETH WAKEUP Exti Line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_IT(__EXTI_LINE__) (EXTI_D1->IMR3 |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTI_GET_FLAG(__EXTI_LINE__) (EXTI_D1->PR3 & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTI_CLEAR_FLAG(__EXTI_LINE__) (EXTI_D1->PR3 = (__EXTI_LINE__)) + +#if defined(DUAL_CORE) +/** + * @brief Enable the ETH WAKEUP Exti Line by Core2. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be enabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTID2_ENABLE_IT(__EXTI_LINE__) (EXTI_D2->IMR3 |= (__EXTI_LINE__)) + +/** + * @brief checks whether the specified ETH WAKEUP Exti interrupt flag is set or not. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval EXTI ETH WAKEUP Line Status. + */ +#define __HAL_ETH_WAKEUP_EXTID2_GET_FLAG(__EXTI_LINE__) (EXTI_D2->PR3 & (__EXTI_LINE__)) + +/** + * @brief Clear the ETH WAKEUP Exti flag. + * @param __EXTI_LINE__: specifies the ETH WAKEUP Exti sources to be cleared. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None. + */ +#define __HAL_ETH_WAKEUP_EXTID2_CLEAR_FLAG(__EXTI_LINE__) (EXTI_D2->PR3 = (__EXTI_LINE__)) +#endif /* DUAL_CORE */ + +/** + * @brief enable rising edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_EDGE(__EXTI_LINE__) (EXTI->FTSR3 &= ~(__EXTI_LINE__)); \ + (EXTI->RTSR3 |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR3 &= ~(__EXTI_LINE__));\ + (EXTI->FTSR3 |= (__EXTI_LINE__)) + +/** + * @brief enable falling edge interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_ENABLE_RISING_FALLING_EDGE(__EXTI_LINE__) (EXTI->RTSR3 |= (__EXTI_LINE__));\ + (EXTI->FTSR3 |= (__EXTI_LINE__)) + +/** + * @brief Generates a Software interrupt on selected EXTI line. + * @param __EXTI_LINE__: specifies the ETH WAKEUP EXTI sources to be disabled. + * @arg ETH_WAKEUP_EXTI_LINE + * @retval None + */ +#define __HAL_ETH_WAKEUP_EXTI_GENERATE_SWIT(__EXTI_LINE__) (EXTI->SWIER3 |= (__EXTI_LINE__)) +#define __HAL_ETH_GET_PTP_CONTROL(__HANDLE__, __FLAG__) (((((__HANDLE__)->Instance->MACTSCR) & \ + (__FLAG__)) == (__FLAG__)) ? SET : RESET) +#define __HAL_ETH_SET_PTP_CONTROL(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->MACTSCR |= (__FLAG__)) + +/** + * @} + */ + +/* Include ETH HAL Extension module */ +#include "stm32h7xx_hal_eth_ex.h" + +/* Exported functions --------------------------------------------------------*/ + +/** @addtogroup ETH_Exported_Functions + * @{ + */ + +/** @addtogroup ETH_Exported_Functions_Group1 + * @{ + */ +/* Initialization and de initialization functions **********************************/ +HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth); +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth); + +/* Callbacks Register/UnRegister functions ***********************************/ +#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1) +HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, + pETH_CallbackTypeDef pCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID); +#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */ + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group2 + * @{ + */ +/* IO operation functions *******************************************************/ +HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Start_IT(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_Stop_IT(ETH_HandleTypeDef *heth); + +HAL_StatusTypeDef HAL_ETH_ReadData(ETH_HandleTypeDef *heth, void **pAppBuff); +HAL_StatusTypeDef HAL_ETH_RegisterRxAllocateCallback(ETH_HandleTypeDef *heth, + pETH_rxAllocateCallbackTypeDef rxAllocateCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxAllocateCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_RegisterRxLinkCallback(ETH_HandleTypeDef *heth, pETH_rxLinkCallbackTypeDef rxLinkCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterRxLinkCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_GetRxDataErrorCode(const ETH_HandleTypeDef *heth, uint32_t *pErrorCode); +HAL_StatusTypeDef HAL_ETH_RegisterTxFreeCallback(ETH_HandleTypeDef *heth, pETH_txFreeCallbackTypeDef txFreeCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxFreeCallback(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_ReleaseTxPacket(ETH_HandleTypeDef *heth); + +#ifdef HAL_ETH_USE_PTP +HAL_StatusTypeDef HAL_ETH_PTP_SetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_GetConfig(ETH_HandleTypeDef *heth, ETH_PTP_ConfigTypeDef *ptpconfig); +HAL_StatusTypeDef HAL_ETH_PTP_SetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_GetTime(ETH_HandleTypeDef *heth, ETH_TimeTypeDef *time); +HAL_StatusTypeDef HAL_ETH_PTP_AddTimeOffset(ETH_HandleTypeDef *heth, ETH_PtpUpdateTypeDef ptpoffsettype, + ETH_TimeTypeDef *timeoffset); +HAL_StatusTypeDef HAL_ETH_PTP_InsertTxTimestamp(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_PTP_GetTxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_PTP_GetRxTimestamp(ETH_HandleTypeDef *heth, ETH_TimeStampTypeDef *timestamp); +HAL_StatusTypeDef HAL_ETH_RegisterTxPtpCallback(ETH_HandleTypeDef *heth, pETH_txPtpCallbackTypeDef txPtpCallback); +HAL_StatusTypeDef HAL_ETH_UnRegisterTxPtpCallback(ETH_HandleTypeDef *heth); +#endif /* HAL_ETH_USE_PTP */ + +HAL_StatusTypeDef HAL_ETH_Transmit(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig, uint32_t Timeout); +HAL_StatusTypeDef HAL_ETH_Transmit_IT(ETH_HandleTypeDef *heth, ETH_TxPacketConfigTypeDef *pTxConfig); + +HAL_StatusTypeDef HAL_ETH_WritePHYRegister(const ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t RegValue); +HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint32_t PHYAddr, uint32_t PHYReg, + uint32_t *pRegValue); + +void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth); +void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_PMTCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_EEECallback(ETH_HandleTypeDef *heth); +void HAL_ETH_WakeUpCallback(ETH_HandleTypeDef *heth); +void HAL_ETH_RxAllocateCallback(uint8_t **buff); +void HAL_ETH_RxLinkCallback(void **pStart, void **pEnd, uint8_t *buff, uint16_t Length); +void HAL_ETH_TxFreeCallback(uint32_t *buff); +void HAL_ETH_TxPtpCallback(uint32_t *buff, ETH_TimeStampTypeDef *timestamp); +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group3 + * @{ + */ +/* Peripheral Control functions **********************************************/ +/* MAC & DMA Configuration APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACConfig(const ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_GetDMAConfig(const ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +HAL_StatusTypeDef HAL_ETH_SetMACConfig(ETH_HandleTypeDef *heth, ETH_MACConfigTypeDef *macconf); +HAL_StatusTypeDef HAL_ETH_SetDMAConfig(ETH_HandleTypeDef *heth, ETH_DMAConfigTypeDef *dmaconf); +void HAL_ETH_SetMDIOClockRange(ETH_HandleTypeDef *heth); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETH_SetRxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t ComparisonBits, + uint32_t VLANIdentifier); + +/* MAC L2 Packet Filtering APIs **********************************************/ +HAL_StatusTypeDef HAL_ETH_GetMACFilterConfig(const ETH_HandleTypeDef *heth, ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetMACFilterConfig(ETH_HandleTypeDef *heth, const ETH_MACFilterConfigTypeDef *pFilterConfig); +HAL_StatusTypeDef HAL_ETH_SetHashTable(ETH_HandleTypeDef *heth, uint32_t *pHashTable); +HAL_StatusTypeDef HAL_ETH_SetSourceMACAddrMatch(const ETH_HandleTypeDef *heth, uint32_t AddrNbr, + const uint8_t *pMACAddr); + +/* MAC Power Down APIs *****************************************************/ +void HAL_ETH_EnterPowerDownMode(ETH_HandleTypeDef *heth, + const ETH_PowerDownConfigTypeDef *pPowerDownConfig); +void HAL_ETH_ExitPowerDownMode(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETH_SetWakeUpFilter(ETH_HandleTypeDef *heth, uint32_t *pFilter, uint32_t Count); + +/** + * @} + */ + +/** @addtogroup ETH_Exported_Functions_Group4 + * @{ + */ +/* Peripheral State functions **************************************************/ +HAL_ETH_StateTypeDef HAL_ETH_GetState(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetDMAError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACError(const ETH_HandleTypeDef *heth); +uint32_t HAL_ETH_GetMACWakeUpSource(const ETH_HandleTypeDef *heth); +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_ETH_H */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.c b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.c new file mode 100644 index 0000000000..feb0cfd629 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.c @@ -0,0 +1,660 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_eth_ex.c + * @author MCD Application Team + * @brief ETH HAL Extended module driver. + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +#ifdef HAL_ETH_MODULE_ENABLED + +#if defined(ETH) + +/** @defgroup ETHEx ETHEx + * @brief ETH HAL Extended module driver + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup ETHEx_Private_Constants ETHEx Private Constants + * @{ + */ +#define ETH_MACL4CR_MASK (ETH_MACL3L4CR_L4PEN | ETH_MACL3L4CR_L4SPM | \ + ETH_MACL3L4CR_L4SPIM | ETH_MACL3L4CR_L4DPM | \ + ETH_MACL3L4CR_L4DPIM) + +#define ETH_MACL3CR_MASK (ETH_MACL3L4CR_L3PEN | ETH_MACL3L4CR_L3SAM | \ + ETH_MACL3L4CR_L3SAIM | ETH_MACL3L4CR_L3DAM | \ + ETH_MACL3L4CR_L3DAIM | ETH_MACL3L4CR_L3HSBM | \ + ETH_MACL3L4CR_L3HDBM) + +#define ETH_MACRXVLAN_MASK (ETH_MACVTR_EIVLRXS | ETH_MACVTR_EIVLS | \ + ETH_MACVTR_ERIVLT | ETH_MACVTR_EDVLP | \ + ETH_MACVTR_VTHM | ETH_MACVTR_EVLRXS | \ + ETH_MACVTR_EVLS | ETH_MACVTR_DOVLTC | \ + ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL | \ + ETH_MACVTR_VTIM | ETH_MACVTR_ETV) + +#define ETH_MACTXVLAN_MASK (ETH_MACVIR_VLTI | ETH_MACVIR_CSVL | \ + ETH_MACVIR_VLP | ETH_MACVIR_VLC) + +#define ETH_MAC_L4_SRSP_MASK 0x0000FFFFU +#define ETH_MAC_L4_DSTP_MASK 0xFFFF0000U +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Exported functions ---------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Functions ETH Extended Exported Functions + * @{ + */ + +/** @defgroup ETHEx_Exported_Functions_Group1 Extended features functions + * @brief Extended features functions + * +@verbatim + =============================================================================== + ##### Extended features functions ##### + =============================================================================== + [..] This section provides functions allowing to: + (+) Configure ARP offload module + (+) Configure L3 and L4 filters + (+) Configure Extended VLAN features + (+) Configure Energy Efficient Ethernet module + +@endverbatim + * @{ + */ + +/** + * @brief Enables ARP Offload. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ + +void HAL_ETHEx_EnableARPOffload(ETH_HandleTypeDef *heth) +{ + SET_BIT(heth->Instance->MACCR, ETH_MACCR_ARP); +} + +/** + * @brief Disables ARP Offload. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETHEx_DisableARPOffload(ETH_HandleTypeDef *heth) +{ + CLEAR_BIT(heth->Instance->MACCR, ETH_MACCR_ARP); +} + +/** + * @brief Set the ARP Match IP address + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param IpAddress: IP Address to be matched for incoming ARP requests + * @retval None + */ +void HAL_ETHEx_SetARPAddressMatch(ETH_HandleTypeDef *heth, uint32_t IpAddress) +{ + WRITE_REG(heth->Instance->MACARPAR, IpAddress); +} + +/** + * @brief Configures the L4 Filter, this function allow to: + * set the layer 4 protocol to be matched (TCP or UDP) + * enable/disable L4 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L4 filter to configured, this parameter must be one of the following + * ETH_L4_FILTER_0 + * ETH_L4_FILTER_1 + * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure + * that contains L4 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L4FilterConfigTypeDef *pL4FilterConfig) +{ + if (pL4FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L4_FILTER_0) + { + /* Write configuration to MACL3L4C0R register */ + MODIFY_REG(heth->Instance->MACL3L4C0R, ETH_MACL4CR_MASK, (pL4FilterConfig->Protocol | + pL4FilterConfig->SrcPortFilterMatch | + pL4FilterConfig->DestPortFilterMatch)); + + /* Write configuration to MACL4A0R register */ + WRITE_REG(heth->Instance->MACL4A0R, (pL4FilterConfig->SourcePort | (pL4FilterConfig->DestinationPort << 16))); + + } + else /* Filter == ETH_L4_FILTER_1 */ + { + /* Write configuration to MACL3L4C1R register */ + MODIFY_REG(heth->Instance->MACL3L4C1R, ETH_MACL4CR_MASK, (pL4FilterConfig->Protocol | + pL4FilterConfig->SrcPortFilterMatch | + pL4FilterConfig->DestPortFilterMatch)); + + /* Write configuration to MACL4A1R register */ + WRITE_REG(heth->Instance->MACL4A1R, (pL4FilterConfig->SourcePort | (pL4FilterConfig->DestinationPort << 16))); + } + + /* Enable L4 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); + + return HAL_OK; +} + +/** + * @brief Configures the L4 Filter, this function allow to: + * set the layer 4 protocol to be matched (TCP or UDP) + * enable/disable L4 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L4 filter to configured, this parameter must be one of the following + * ETH_L4_FILTER_0 + * ETH_L4_FILTER_1 + * @param pL4FilterConfig: pointer to a ETH_L4FilterConfigTypeDef structure + * that contains L4 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetL4FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L4FilterConfigTypeDef *pL4FilterConfig) +{ + if (pL4FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L4_FILTER_0) + { + /* Get configuration from MACL3L4C0R register */ + pL4FilterConfig->Protocol = READ_BIT(heth->Instance->MACL3L4C0R, ETH_MACL3L4CR_L4PEN); + pL4FilterConfig->DestPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C0R, + (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM)); + pL4FilterConfig->SrcPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C0R, + (ETH_MACL3L4CR_L4SPM | ETH_MACL3L4CR_L4SPIM)); + + /* Get configuration from MACL4A0R register */ + pL4FilterConfig->DestinationPort = (READ_BIT(heth->Instance->MACL4A0R, ETH_MAC_L4_DSTP_MASK) >> 16); + pL4FilterConfig->SourcePort = READ_BIT(heth->Instance->MACL4A0R, ETH_MAC_L4_SRSP_MASK); + } + else /* Filter == ETH_L4_FILTER_1 */ + { + /* Get configuration from MACL3L4C1R register */ + pL4FilterConfig->Protocol = READ_BIT(heth->Instance->MACL3L4C1R, ETH_MACL3L4CR_L4PEN); + pL4FilterConfig->DestPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C1R, + (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM)); + pL4FilterConfig->SrcPortFilterMatch = READ_BIT(heth->Instance->MACL3L4C1R, + (ETH_MACL3L4CR_L4SPM | ETH_MACL3L4CR_L4SPIM)); + + /* Get configuration from MACL4A1R register */ + pL4FilterConfig->DestinationPort = (READ_BIT(heth->Instance->MACL4A1R, ETH_MAC_L4_DSTP_MASK) >> 16); + pL4FilterConfig->SourcePort = READ_BIT(heth->Instance->MACL4A1R, ETH_MAC_L4_SRSP_MASK); + } + + return HAL_OK; +} + +/** + * @brief Configures the L3 Filter, this function allow to: + * set the layer 3 protocol to be matched (IPv4 or IPv6) + * enable/disable L3 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L3 filter to configured, this parameter must be one of the following + * ETH_L3_FILTER_0 + * ETH_L3_FILTER_1 + * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure + * that contains L3 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L3FilterConfigTypeDef *pL3FilterConfig) +{ + if (pL3FilterConfig == NULL) + { + return HAL_ERROR; + } + + if (Filter == ETH_L3_FILTER_0) + { + /* Write configuration to MACL3L4C0R register */ + MODIFY_REG(heth->Instance->MACL3L4C0R, ETH_MACL3CR_MASK, (pL3FilterConfig->Protocol | + pL3FilterConfig->SrcAddrFilterMatch | + pL3FilterConfig->DestAddrFilterMatch | + (pL3FilterConfig->SrcAddrHigherBitsMatch << 6) | + (pL3FilterConfig->DestAddrHigherBitsMatch << 11))); + } + else /* Filter == ETH_L3_FILTER_1 */ + { + /* Write configuration to MACL3L4C1R register */ + MODIFY_REG(heth->Instance->MACL3L4C1R, ETH_MACL3CR_MASK, (pL3FilterConfig->Protocol | + pL3FilterConfig->SrcAddrFilterMatch | + pL3FilterConfig->DestAddrFilterMatch | + (pL3FilterConfig->SrcAddrHigherBitsMatch << 6) | + (pL3FilterConfig->DestAddrHigherBitsMatch << 11))); + } + + if (Filter == ETH_L3_FILTER_0) + { + /* Check if IPv6 protocol is selected */ + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + /* Set the IPv6 address match */ + /* Set Bits[31:0] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A0R0R, pL3FilterConfig->Ip6Addr[0]); + /* Set Bits[63:32] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R0R, pL3FilterConfig->Ip6Addr[1]); + /* update Bits[95:64] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A2R0R, pL3FilterConfig->Ip6Addr[2]); + /* update Bits[127:96] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A3R0R, pL3FilterConfig->Ip6Addr[3]); + } + else /* IPv4 protocol is selected */ + { + /* Set the IPv4 source address match */ + WRITE_REG(heth->Instance->MACL3A0R0R, pL3FilterConfig->Ip4SrcAddr); + /* Set the IPv4 destination address match */ + WRITE_REG(heth->Instance->MACL3A1R0R, pL3FilterConfig->Ip4DestAddr); + } + } + else /* Filter == ETH_L3_FILTER_1 */ + { + /* Check if IPv6 protocol is selected */ + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + /* Set the IPv6 address match */ + /* Set Bits[31:0] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip6Addr[0]); + /* Set Bits[63:32] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[1]); + /* update Bits[95:64] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[2]); + /* update Bits[127:96] of 128-bit IP addr */ + WRITE_REG(heth->Instance->MACL3A1R1R, pL3FilterConfig->Ip6Addr[3]); + } + else /* IPv4 protocol is selected */ + { + /* Set the IPv4 source address match */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip4SrcAddr); + /* Set the IPv4 destination address match */ + WRITE_REG(heth->Instance->MACL3A0R1R, pL3FilterConfig->Ip4DestAddr); + + } + } + + /* Enable L3 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); + + return HAL_OK; +} + +/** + * @brief Configures the L3 Filter, this function allow to: + * set the layer 3 protocol to be matched (IPv4 or IPv6) + * enable/disable L3 source/destination port perfect/inverse match. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param Filter: L3 filter to configured, this parameter must be one of the following + * ETH_L3_FILTER_0 + * ETH_L3_FILTER_1 + * @param pL3FilterConfig: pointer to a ETH_L3FilterConfigTypeDef structure + * that will contain the L3 filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetL3FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L3FilterConfigTypeDef *pL3FilterConfig) +{ + if (pL3FilterConfig == NULL) + { + return HAL_ERROR; + } + pL3FilterConfig->Protocol = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3PEN); + pL3FilterConfig->SrcAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + (ETH_MACL3L4CR_L3SAM | ETH_MACL3L4CR_L3SAIM)); + pL3FilterConfig->DestAddrFilterMatch = READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + (ETH_MACL3L4CR_L3DAM | ETH_MACL3L4CR_L3DAIM)); + pL3FilterConfig->SrcAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3HSBM) >> 6); + pL3FilterConfig->DestAddrHigherBitsMatch = (READ_BIT(*((__IO uint32_t *)(&(heth->Instance->MACL3L4C0R) + Filter)), + ETH_MACL3L4CR_L3HDBM) >> 11); + + if (Filter == ETH_L3_FILTER_0) + { + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + WRITE_REG(pL3FilterConfig->Ip6Addr[0], heth->Instance->MACL3A0R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[1], heth->Instance->MACL3A1R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[2], heth->Instance->MACL3A2R0R); + WRITE_REG(pL3FilterConfig->Ip6Addr[3], heth->Instance->MACL3A3R0R); + } + else + { + WRITE_REG(pL3FilterConfig->Ip4SrcAddr, heth->Instance->MACL3A0R0R); + WRITE_REG(pL3FilterConfig->Ip4DestAddr, heth->Instance->MACL3A1R0R); + } + } + else /* ETH_L3_FILTER_1 */ + { + if (pL3FilterConfig->Protocol != ETH_L3_IPV4_MATCH) + { + WRITE_REG(pL3FilterConfig->Ip6Addr[0], heth->Instance->MACL3A0R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[1], heth->Instance->MACL3A1R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[2], heth->Instance->MACL3A2R1R); + WRITE_REG(pL3FilterConfig->Ip6Addr[3], heth->Instance->MACL3A3R1R); + } + else + { + WRITE_REG(pL3FilterConfig->Ip4SrcAddr, heth->Instance->MACL3A0R1R); + WRITE_REG(pL3FilterConfig->Ip4DestAddr, heth->Instance->MACL3A1R1R); + } + } + + return HAL_OK; +} + +/** + * @brief Enables L3 and L4 filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_EnableL3L4Filtering(ETH_HandleTypeDef *heth) +{ + /* Enable L3/L4 filter */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); +} + +/** + * @brief Disables L3 and L4 filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_DisableL3L4Filtering(ETH_HandleTypeDef *heth) +{ + /* Disable L3/L4 filter */ + CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_IPFE); +} + +/** + * @brief Get the VLAN Configuration for Receive Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure + * that will contain the VLAN filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_GetRxVLANConfig(const ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + pVlanConfig->InnerVLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EIVLRXS) >> 31) == 0U) ? DISABLE : ENABLE; + pVlanConfig->StripInnerVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EIVLS); + pVlanConfig->InnerVLANTag = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_ERIVLT) >> 27) == 0U) ? DISABLE : ENABLE; + pVlanConfig->DoubleVLANProcessing = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EDVLP) >> 26) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagHashTableMatch = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_VTHM) >> 25) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagInStatus = ((READ_BIT(heth->Instance->MACVTR, + ETH_MACVTR_EVLRXS) >> 24) == 0U) ? DISABLE : ENABLE; + pVlanConfig->StripVLANTag = READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_EVLS); + pVlanConfig->VLANTypeCheck = READ_BIT(heth->Instance->MACVTR, + (ETH_MACVTR_DOVLTC | ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL)); + pVlanConfig->VLANTagInverceMatch = ((READ_BIT(heth->Instance->MACVTR, ETH_MACVTR_VTIM) >> 17) == 0U) + ? DISABLE : ENABLE; + + return HAL_OK; +} + +/** + * @brief Set the VLAN Configuration for Receive Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param pVlanConfig: pointer to a ETH_RxVLANConfigTypeDef structure + * that contains VLAN filter configuration. + * @retval HAL status + */ +HAL_StatusTypeDef HAL_ETHEx_SetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + /* Write config to MACVTR */ + MODIFY_REG(heth->Instance->MACVTR, ETH_MACRXVLAN_MASK, (((uint32_t)pVlanConfig->InnerVLANTagInStatus << 31) | + pVlanConfig->StripInnerVLANTag | + ((uint32_t)pVlanConfig->InnerVLANTag << 27) | + ((uint32_t)pVlanConfig->DoubleVLANProcessing << 26) | + ((uint32_t)pVlanConfig->VLANTagHashTableMatch << 25) | + ((uint32_t)pVlanConfig->VLANTagInStatus << 24) | + pVlanConfig->StripVLANTag | + pVlanConfig->VLANTypeCheck | + ((uint32_t)pVlanConfig->VLANTagInverceMatch << 17))); + + return HAL_OK; +} + +/** + * @brief Set the VLAN Hash Table + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANHashTable: VLAN hash table 16 bit value + * @retval None + */ +void HAL_ETHEx_SetVLANHashTable(ETH_HandleTypeDef *heth, uint32_t VLANHashTable) +{ + MODIFY_REG(heth->Instance->MACVHTR, ETH_MACVHTR_VLHT, VLANHashTable); +} + +/** + * @brief Get the VLAN Configuration for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure + * that will contain the Tx VLAN filter configuration. + * @retval HAL Status. + */ +HAL_StatusTypeDef HAL_ETHEx_GetTxVLANConfig(const ETH_HandleTypeDef *heth, uint32_t VLANTag, + ETH_TxVLANConfigTypeDef *pVlanConfig) +{ + if (pVlanConfig == NULL) + { + return HAL_ERROR; + } + + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE; + pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACIVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACIVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC)); + } + else + { + pVlanConfig->SourceTxDesc = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_VLTI) >> 20) == 0U) ? DISABLE : ENABLE; + pVlanConfig->SVLANType = ((READ_BIT(heth->Instance->MACVIR, ETH_MACVIR_CSVL) >> 19) == 0U) ? DISABLE : ENABLE; + pVlanConfig->VLANTagControl = READ_BIT(heth->Instance->MACVIR, (ETH_MACVIR_VLP | ETH_MACVIR_VLC)); + } + + return HAL_OK;; +} + +/** + * @brief Set the VLAN Configuration for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param pVlanConfig: pointer to a ETH_TxVLANConfigTypeDef structure + * that contains Tx VLAN filter configuration. + * @retval HAL Status + */ +HAL_StatusTypeDef HAL_ETHEx_SetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag, + const ETH_TxVLANConfigTypeDef *pVlanConfig) +{ + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + MODIFY_REG(heth->Instance->MACIVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) | + ((uint32_t)pVlanConfig->SVLANType << 19) | + pVlanConfig->VLANTagControl)); + /* Enable Double VLAN processing */ + SET_BIT(heth->Instance->MACVTR, ETH_MACVTR_EDVLP); + } + else + { + MODIFY_REG(heth->Instance->MACVIR, ETH_MACTXVLAN_MASK, (((uint32_t)pVlanConfig->SourceTxDesc << 20) | + ((uint32_t)pVlanConfig->SVLANType << 19) | + pVlanConfig->VLANTagControl)); + } + + return HAL_OK; +} + +/** + * @brief Set the VLAN Tag Identifier for Transmit Packets. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param VLANTag: Selects the vlan tag, this parameter must be one of the following + * ETH_OUTER_TX_VLANTAG + * ETH_INNER_TX_VLANTAG + * @param VLANIdentifier: VLAN Identifier 16 bit value + * @retval None + */ +void HAL_ETHEx_SetTxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t VLANTag, uint32_t VLANIdentifier) +{ + if (VLANTag == ETH_INNER_TX_VLANTAG) + { + MODIFY_REG(heth->Instance->MACIVIR, ETH_MACVIR_VLT, VLANIdentifier); + } + else + { + MODIFY_REG(heth->Instance->MACVIR, ETH_MACVIR_VLT, VLANIdentifier); + } +} + +/** + * @brief Enables the VLAN Tag Filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_EnableVLANProcessing(ETH_HandleTypeDef *heth) +{ + /* Enable VLAN processing */ + SET_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE); +} + +/** + * @brief Disables the VLAN Tag Filtering process. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None. + */ +void HAL_ETHEx_DisableVLANProcessing(ETH_HandleTypeDef *heth) +{ + /* Disable VLAN processing */ + CLEAR_BIT(heth->Instance->MACPFR, ETH_MACPFR_VTFE); +} + +/** + * @brief Enters the Low Power Idle (LPI) mode + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @param TxAutomate: Enable/Disable automate enter/exit LPI mode. + * @param TxClockStop: Enable/Disable Tx clock stop in LPI mode. + * @retval None + */ +void HAL_ETHEx_EnterLPIMode(ETH_HandleTypeDef *heth, FunctionalState TxAutomate, FunctionalState TxClockStop) +{ + /* Enable LPI Interrupts */ + __HAL_ETH_MAC_ENABLE_IT(heth, ETH_MACIER_LPIIE); + + /* Write to LPI Control register: Enter low power mode */ + MODIFY_REG(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE), + (((uint32_t)TxAutomate << 19) | + ((uint32_t)TxClockStop << 21) | + ETH_MACLCSR_LPIEN)); +} + +/** + * @brief Exits the Low Power Idle (LPI) mode. + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval None + */ +void HAL_ETHEx_ExitLPIMode(ETH_HandleTypeDef *heth) +{ + /* Clear the LPI Config and exit low power mode */ + CLEAR_BIT(heth->Instance->MACLCSR, (ETH_MACLCSR_LPIEN | ETH_MACLCSR_LPITXA | ETH_MACLCSR_LPITCSE)); + + /* Enable LPI Interrupts */ + __HAL_ETH_MAC_DISABLE_IT(heth, ETH_MACIER_LPIIE); +} + +/** + * @brief Returns the ETH MAC LPI event + * @param heth: pointer to a ETH_HandleTypeDef structure that contains + * the configuration information for ETHERNET module + * @retval ETH MAC WakeUp event + */ +uint32_t HAL_ETHEx_GetMACLPIEvent(const ETH_HandleTypeDef *heth) +{ + return heth->MACLPIEvent; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#endif /* HAL_ETH_MODULE_ENABLED */ +/** + * @} + */ diff --git a/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.h b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.h new file mode 100644 index 0000000000..4e229bc852 --- /dev/null +++ b/source/portable/NetworkInterface/STM32/Drivers/H7/stm32h7xx_hal_eth_ex.h @@ -0,0 +1,366 @@ +/** + ****************************************************************************** + * @file stm32h7xx_hal_eth_ex.h + * @author MCD Application Team + * @brief Header file of ETH HAL Extended module. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef STM32H7xx_HAL_ETH_EX_H +#define STM32H7xx_HAL_ETH_EX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(ETH) + +/* Includes ------------------------------------------------------------------*/ +#include "stm32h7xx_hal_def.h" + +/** @addtogroup STM32H7xx_HAL_Driver + * @{ + */ + +/** @addtogroup ETHEx + * @{ + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Types ETHEx Exported Types + * @{ + */ + +/** + * @brief ETH RX VLAN structure definition + */ +typedef struct +{ + FunctionalState InnerVLANTagInStatus; /*!< Enables or disables Inner VLAN Tag in Rx Status */ + + uint32_t StripInnerVLANTag; /*!< Sets the Inner VLAN Tag Stripping on Receive + This parameter can be a value of + @ref ETHEx_Rx_Inner_VLAN_Tag_Stripping */ + + FunctionalState InnerVLANTag; /*!< Enables or disables Inner VLAN Tag */ + + FunctionalState DoubleVLANProcessing; /*!< Enable or Disable double VLAN processing */ + + FunctionalState VLANTagHashTableMatch; /*!< Enable or Disable VLAN Tag Hash Table Match */ + + FunctionalState VLANTagInStatus; /*!< Enable or Disable VLAN Tag in Rx status */ + + uint32_t StripVLANTag; /*!< Set the VLAN Tag Stripping on Receive + This parameter can be a value of @ref ETHEx_Rx_VLAN_Tag_Stripping */ + + uint32_t VLANTypeCheck; /*!< Enable or Disable VLAN Type Check + This parameter can be a value of @ref ETHEx_VLAN_Type_Check */ + + FunctionalState VLANTagInverceMatch; /*!< Enable or disable VLAN Tag Inverse Match */ +} ETH_RxVLANConfigTypeDef; +/** + * + */ + +/** + * @brief ETH TX VLAN structure definition + */ +typedef struct +{ + FunctionalState SourceTxDesc; /*!< Enable or Disable VLAN tag source from DMA tx descriptors */ + + FunctionalState SVLANType; /*!< Enable or Disable insertion of SVLAN type */ + + uint32_t VLANTagControl; /*!< Sets the VLAN tag control in tx packets + This parameter can be a value of @ref ETHEx_VLAN_Tag_Control */ +} ETH_TxVLANConfigTypeDef; +/** + * + */ + +/** + * @brief ETH L3 filter structure definition + */ +typedef struct +{ + uint32_t Protocol; /*!< Sets the L3 filter protocol to IPv4 or IPv6 + This parameter can be a value of @ref ETHEx_L3_Protocol */ + + uint32_t SrcAddrFilterMatch; /*!< Sets the L3 filter source address match + This parameter can be a value of @ref ETHEx_L3_Source_Match */ + + uint32_t DestAddrFilterMatch; /*!< Sets the L3 filter destination address match + This parameter can be a value of @ref ETHEx_L3_Destination_Match */ + + uint32_t SrcAddrHigherBitsMatch; /*!< Sets the L3 filter source address higher bits match + This parameter can be a value from 0 to 31 */ + + uint32_t DestAddrHigherBitsMatch; /*!< Sets the L3 filter destination address higher bits match + This parameter can be a value from 0 to 31 */ + + uint32_t Ip4SrcAddr; /*!< Sets the L3 filter IPv4 source address if IPv4 protocol is used + This parameter can be a value from 0x0 to 0xFFFFFFFF */ + + uint32_t Ip4DestAddr; /*!< Sets the L3 filter IPv4 destination address if IPv4 protocol is used + This parameter can be a value from 0 to 0xFFFFFFFF */ + + uint32_t Ip6Addr[4]; /*!< Sets the L3 filter IPv6 address if IPv6 protocol is used + This parameter must be a table of 4 words (4* 32 bits) */ +} ETH_L3FilterConfigTypeDef; +/** + * + */ + +/** + * @brief ETH L4 filter structure definition + */ +typedef struct +{ + uint32_t Protocol; /*!< Sets the L4 filter protocol to TCP or UDP + This parameter can be a value of @ref ETHEx_L4_Protocol */ + + uint32_t SrcPortFilterMatch; /*!< Sets the L4 filter source port match + This parameter can be a value of @ref ETHEx_L4_Source_Match */ + + uint32_t DestPortFilterMatch; /*!< Sets the L4 filter destination port match + This parameter can be a value of @ref ETHEx_L4_Destination_Match */ + + uint32_t SourcePort; /*!< Sets the L4 filter source port + This parameter must be a value from 0x0 to 0xFFFF */ + + uint32_t DestinationPort; /*!< Sets the L4 filter destination port + This parameter must be a value from 0x0 to 0xFFFF */ +} ETH_L4FilterConfigTypeDef; +/** + * + */ + +/** + * @} + */ + +/* Exported constants --------------------------------------------------------*/ +/** @defgroup ETHEx_Exported_Constants ETHEx Exported Constants + * @{ + */ + +/** @defgroup ETHEx_LPI_Event ETHEx LPI Event + * @{ + */ +#define ETH_TX_LPI_ENTRY ETH_MACLCSR_TLPIEN +#define ETH_TX_LPI_EXIT ETH_MACLCSR_TLPIEX +#define ETH_RX_LPI_ENTRY ETH_MACLCSR_RLPIEN +#define ETH_RX_LPI_EXIT ETH_MACLCSR_RLPIEX +/** + * @} + */ + +/** @defgroup ETHEx_L3_Filter ETHEx L3 Filter + * @{ + */ +#define ETH_L3_FILTER_0 0x00000000U +#define ETH_L3_FILTER_1 0x0000000CU +/** + * @} + */ + +/** @defgroup ETHEx_L4_Filter ETHEx L4 Filter + * @{ + */ +#define ETH_L4_FILTER_0 0x00000000U +#define ETH_L4_FILTER_1 0x0000000CU +/** + * @} + */ + +/** @defgroup ETHEx_L3_Protocol ETHEx L3 Protocol + * @{ + */ +#define ETH_L3_IPV6_MATCH ETH_MACL3L4CR_L3PEN +#define ETH_L3_IPV4_MATCH 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L3_Source_Match ETHEx L3 Source Match + * @{ + */ +#define ETH_L3_SRC_ADDR_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L3SAM +#define ETH_L3_SRC_ADDR_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L3SAM | ETH_MACL3L4CR_L3SAIM) +#define ETH_L3_SRC_ADDR_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L3_Destination_Match ETHEx L3 Destination Match + * @{ + */ +#define ETH_L3_DEST_ADDR_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L3DAM +#define ETH_L3_DEST_ADDR_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L3DAM | ETH_MACL3L4CR_L3DAIM) +#define ETH_L3_DEST_ADDR_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Protocol ETHEx L4 Protocol + * @{ + */ +#define ETH_L4_UDP_MATCH ETH_MACL3L4CR_L4PEN +#define ETH_L4_TCP_MATCH 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Source_Match ETHEx L4 Source Match + * @{ + */ +#define ETH_L4_SRC_PORT_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L4SPM +#define ETH_L4_SRC_PORT_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L4SPM |ETH_MACL3L4CR_L4SPIM) +#define ETH_L4_SRC_PORT_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_L4_Destination_Match ETHEx L4 Destination Match + * @{ + */ +#define ETH_L4_DEST_PORT_PERFECT_MATCH_ENABLE ETH_MACL3L4CR_L4DPM +#define ETH_L4_DEST_PORT_INVERSE_MATCH_ENABLE (ETH_MACL3L4CR_L4DPM | ETH_MACL3L4CR_L4DPIM) +#define ETH_L4_DEST_PORT_MATCH_DISABLE 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_Rx_Inner_VLAN_Tag_Stripping ETHEx Rx Inner VLAN Tag Stripping + * @{ + */ +#define ETH_INNERVLANTAGRXSTRIPPING_NONE ETH_MACVTR_EIVLS_DONOTSTRIP +#define ETH_INNERVLANTAGRXSTRIPPING_IFPASS ETH_MACVTR_EIVLS_STRIPIFPASS +#define ETH_INNERVLANTAGRXSTRIPPING_IFFAILS ETH_MACVTR_EIVLS_STRIPIFFAILS +#define ETH_INNERVLANTAGRXSTRIPPING_ALWAYS ETH_MACVTR_EIVLS_ALWAYSSTRIP +/** + * @} + */ + +/** @defgroup ETHEx_Rx_VLAN_Tag_Stripping ETHEx Rx VLAN Tag Stripping + * @{ + */ +#define ETH_VLANTAGRXSTRIPPING_NONE ETH_MACVTR_EVLS_DONOTSTRIP +#define ETH_VLANTAGRXSTRIPPING_IFPASS ETH_MACVTR_EVLS_STRIPIFPASS +#define ETH_VLANTAGRXSTRIPPING_IFFAILS ETH_MACVTR_EVLS_STRIPIFFAILS +#define ETH_VLANTAGRXSTRIPPING_ALWAYS ETH_MACVTR_EVLS_ALWAYSSTRIP +/** + * @} + */ + +/** @defgroup ETHEx_VLAN_Type_Check ETHEx VLAN Type Check + * @{ + */ +#define ETH_VLANTYPECHECK_DISABLE ETH_MACVTR_DOVLTC +#define ETH_VLANTYPECHECK_SVLAN (ETH_MACVTR_ERSVLM | ETH_MACVTR_ESVL) +#define ETH_VLANTYPECHECK_CVLAN 0x00000000U +/** + * @} + */ + +/** @defgroup ETHEx_VLAN_Tag_Control ETHEx_VLAN_Tag_Control + * @{ + */ +#define ETH_VLANTAGCONTROL_NONE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_NOVLANTAG) +#define ETH_VLANTAGCONTROL_DELETE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGDELETE) +#define ETH_VLANTAGCONTROL_INSERT (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGINSERT) +#define ETH_VLANTAGCONTROL_REPLACE (ETH_MACVIR_VLP | ETH_MACVIR_VLC_VLANTAGREPLACE) +/** + * @} + */ + +/** @defgroup ETHEx_Tx_VLAN_Tag ETHEx Tx VLAN Tag + * @{ + */ +#define ETH_INNER_TX_VLANTAG 0x00000001U +#define ETH_OUTER_TX_VLANTAG 0x00000000U +/** + * @} + */ + +/** + * @} + */ + +/* Exported functions --------------------------------------------------------*/ +/** @addtogroup ETHEx_Exported_Functions + * @{ + */ + +/** @addtogroup ETHEx_Exported_Functions_Group1 + * @{ + */ +/* MAC ARP Offloading APIs ***************************************************/ +void HAL_ETHEx_EnableARPOffload(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableARPOffload(ETH_HandleTypeDef *heth); +void HAL_ETHEx_SetARPAddressMatch(ETH_HandleTypeDef *heth, uint32_t IpAddress); + +/* MAC L3 L4 Filtering APIs ***************************************************/ +void HAL_ETHEx_EnableL3L4Filtering(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableL3L4Filtering(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETHEx_GetL3FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L3FilterConfigTypeDef *pL3FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_GetL4FilterConfig(const ETH_HandleTypeDef *heth, uint32_t Filter, + ETH_L4FilterConfigTypeDef *pL4FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_SetL3FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L3FilterConfigTypeDef *pL3FilterConfig); +HAL_StatusTypeDef HAL_ETHEx_SetL4FilterConfig(ETH_HandleTypeDef *heth, uint32_t Filter, + const ETH_L4FilterConfigTypeDef *pL4FilterConfig); + +/* MAC VLAN Processing APIs ************************************************/ +void HAL_ETHEx_EnableVLANProcessing(ETH_HandleTypeDef *heth); +void HAL_ETHEx_DisableVLANProcessing(ETH_HandleTypeDef *heth); +HAL_StatusTypeDef HAL_ETHEx_GetRxVLANConfig(const ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig); +HAL_StatusTypeDef HAL_ETHEx_SetRxVLANConfig(ETH_HandleTypeDef *heth, ETH_RxVLANConfigTypeDef *pVlanConfig); +void HAL_ETHEx_SetVLANHashTable(ETH_HandleTypeDef *heth, uint32_t VLANHashTable); +HAL_StatusTypeDef HAL_ETHEx_GetTxVLANConfig(const ETH_HandleTypeDef *heth, uint32_t VLANTag, + ETH_TxVLANConfigTypeDef *pVlanConfig); +HAL_StatusTypeDef HAL_ETHEx_SetTxVLANConfig(ETH_HandleTypeDef *heth, uint32_t VLANTag, + const ETH_TxVLANConfigTypeDef *pVlanConfig); +void HAL_ETHEx_SetTxVLANIdentifier(ETH_HandleTypeDef *heth, uint32_t VLANTag, uint32_t VLANIdentifier); + +/* Energy Efficient Ethernet APIs *********************************************/ +void HAL_ETHEx_EnterLPIMode(ETH_HandleTypeDef *heth, FunctionalState TxAutomate, + FunctionalState TxClockStop); +void HAL_ETHEx_ExitLPIMode(ETH_HandleTypeDef *heth); +uint32_t HAL_ETHEx_GetMACLPIEvent(const ETH_HandleTypeDef *heth); + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +#endif /* ETH */ + +#ifdef __cplusplus +} +#endif + +#endif /* STM32H7xx_HAL_ETH_EX_H */ From b278985fe6a6946ed111c1af3b237d4f16e0efbf Mon Sep 17 00:00:00 2001 From: Holden Date: Fri, 5 Jul 2024 00:28:31 -0400 Subject: [PATCH 63/68] Handle Driver Differences --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 8bf5333a99..a850c731c1 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -602,6 +602,7 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, break; } + // ETH_TxPacketConfigTypeDef ETH_TxPacketConfig xTxConfig = { .CRCPadCtrl = ETH_CRC_PAD_INSERT, @@ -1195,7 +1196,7 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) prvAddAllowedMACAddress( pxInterface, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) - prvAddAllowedMACAddress( pxInterface, xMDNS_MACAddressIPv6.ucBytes ); + prvAddAllowedMACAddress( pxInterface, xMDNS_MacAddressIPv6.ucBytes ); #endif #if ipconfigIS_ENABLED( ipconfigUSE_LLMNR ) prvAddAllowedMACAddress( pxInterface, xLLMNR_MacAddressIPv6.ucBytes ); From 4e0ab396aaf6c6e40277c851df6299a07fe1f612 Mon Sep 17 00:00:00 2001 From: "Ching-Hsin,Lee" Date: Fri, 12 Jul 2024 15:53:42 +0800 Subject: [PATCH 64/68] Exclude portable STM32 for spelling and formating check --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba6a8c1660..ad02a0a9b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,6 +126,7 @@ jobs: uses: FreeRTOS/CI-CD-Github-Actions/spellings@main with: path: ./ + exclude-dirs: source/portable/NetworkInterface/STM32 formatting: runs-on: ubuntu-20.04 @@ -135,6 +136,7 @@ jobs: uses: FreeRTOS/CI-CD-Github-Actions/formatting@main with: path: ./ + exclude-dirs: source/portable/NetworkInterface/STM32 doxygen: runs-on: ubuntu-latest From c18bfe757b050e8e960abe3e7b34d06ee0dee7cc Mon Sep 17 00:00:00 2001 From: Holden <68555040+HTRamsey@users.noreply.github.com> Date: Fri, 12 Jul 2024 14:45:16 -0400 Subject: [PATCH 65/68] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Błażej Sowa --- .../NetworkInterface/STM32/CMakeLists.txt | 26 +++++++++++++++++++ .../NetworkInterface/STM32/NetworkInterface.c | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/CMakeLists.txt b/source/portable/NetworkInterface/STM32/CMakeLists.txt index 4d019b1c28..0b30b2821c 100644 --- a/source/portable/NetworkInterface/STM32/CMakeLists.txt +++ b/source/portable/NetworkInterface/STM32/CMakeLists.txt @@ -5,9 +5,35 @@ endif() #------------------------------------------------------------------------------ add_library( freertos_plus_tcp_network_if STATIC ) +set( FREERTOS_PLUS_TCP_STM32_IF_DRIVER "None" CACHE STRING "The driver sources to use with STM32 Network interface" ) + target_sources( freertos_plus_tcp_network_if PRIVATE NetworkInterface.c + $<$: + Drivers/F4/stm32f4xx_hal_eth.c> + $<$: + Drivers/F7/stm32f7xx_hal_eth.c> + $<$: + Drivers/H5/stm32h5xx_hal_eth_ex.c> + $<$: + Drivers/H5/stm32h5xx_hal_eth.c> + $<$: + Drivers/H7/stm32h7xx_hal_eth_ex.c> + $<$: + Drivers/H7/stm32h7xx_hal_eth.c> +) + +target_include_directories( freertos_plus_tcp_network_if + PUBLIC + $<$: + Drivers/F4> + $<$: + Drivers/F7> + $<$: + Drivers/H5> + $<$: + Drivers/H7> ) target_link_libraries( freertos_plus_tcp_network_if diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index a850c731c1..93e9121d2c 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1194,7 +1194,7 @@ static void prvInitMacAddresses( ETH_HandleTypeDef * pxEthHandle, #endif #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - prvAddAllowedMACAddress( pxInterface, pcLOCAL_ALL_NODES_MULTICAST_MAC.ucBytes ); + prvAddAllowedMACAddress( pxInterface, pcLOCAL_ALL_NODES_MULTICAST_MAC ); #if ipconfigIS_ENABLED( ipconfigUSE_MDNS ) prvAddAllowedMACAddress( pxInterface, xMDNS_MacAddressIPv6.ucBytes ); #endif From 0abb36bd9662e165d23f40059b0a595adaf76126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Sowa?= Date: Wed, 17 Jul 2024 17:57:35 +0200 Subject: [PATCH 66/68] Increment MAC entry index --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 93e9121d2c..107330657e 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -1570,7 +1570,7 @@ static BaseType_t prvSetNewDestMACAddrMatch( ETH_TypeDef * const pxEthInstance, if( ucAddrHashCounters[ ucHashIndex ] == 0U ) { prvHAL_ETH_SetDestMACAddrMatch( pxEthInstance, uxMACEntryIndex, pucMACAddr ); - ucSrcMatchCounters[ uxMACEntryIndex ] = 1U; + ucSrcMatchCounters[ uxMACEntryIndex++ ] = 1U; xResult = pdTRUE; } } From 445dc68b237e32e6e1ea49aade3b3a3e33d3add6 Mon Sep 17 00:00:00 2001 From: Holden Date: Wed, 31 Jul 2024 21:57:23 -0400 Subject: [PATCH 67/68] Fix packet length assert --- source/portable/NetworkInterface/STM32/NetworkInterface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 107330657e..2c6fbfa147 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -840,7 +840,7 @@ static BaseType_t prvNetworkInterfaceInput( ETH_HandleTypeDef * pxEthHandle, continue; } - configASSERT( pxEthHandle->RxDescList.RxDataLength <= niEMAC_DATA_BUFFER_SIZE ); + configASSERT( pxCurDescriptor->xDataLength <= niEMAC_DATA_BUFFER_SIZE ); pxCurDescriptor->pxInterface = pxInterface; pxCurDescriptor->pxEndPoint = FreeRTOS_MatchingEndpoint( pxCurDescriptor->pxInterface, pxCurDescriptor->pucEthernetBuffer ); From 125b153badec0527e3f98c12cab74b5b207a57d0 Mon Sep 17 00:00:00 2001 From: Holden Date: Thu, 19 Sep 2024 07:02:47 -0400 Subject: [PATCH 68/68] Review Fixes --- .../NetworkInterface/STM32/NetworkInterface.c | 71 +------------------ 1 file changed, 3 insertions(+), 68 deletions(-) diff --git a/source/portable/NetworkInterface/STM32/NetworkInterface.c b/source/portable/NetworkInterface/STM32/NetworkInterface.c index 2c6fbfa147..edc79b5f08 100644 --- a/source/portable/NetworkInterface/STM32/NetworkInterface.c +++ b/source/portable/NetworkInterface/STM32/NetworkInterface.c @@ -635,75 +635,10 @@ static BaseType_t prvNetworkInterfaceOutput( NetworkInterface_t * pxInterface, FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported ICMP\n" ) ); #endif } - else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_TCP ) - { - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) - TCPPacket_t * const pxTCPPacket = ( TCPPacket_t * const ) pxDescriptor->pucEthernetBuffer; - - /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) - * xTxConfig.MaxSegmentSize = ipconfigTCP_MSS; - * xTxConfig.PayloadLen = pxDescriptor->xDataLength; - * xTxConfig.TCPHeaderLen = ( pxTCPPacket->xIPHeader.ucVersionHeaderLength & ( uint8_t ) 0x0FU ); - * xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif */ - ( void ) pxTCPPacket; - #else - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); - #endif - } - else if( pxIPPacket->xIPHeader.ucProtocol == ipPROTOCOL_UDP ) - { - UDPPacket_t * const pxUDPPacket = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; - ( void ) pxUDPPacket; - } #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv4\n" ) ); #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv4 ) */ } - else if( pxEthHeader->usFrameType == ipIPv6_FRAME_TYPE ) - { - #if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) - const IPPacket_IPv6_t * pxIPPacket_IPv6 = ( IPPacket_IPv6_t * ) pxDescriptor->pucEthernetBuffer; - - if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_ICMP_IPv6 ) - { - #if ipconfigIS_ENABLED( ipconfigREPLY_TO_INCOMING_PINGS ) || ipconfigIS_ENABLED( ipconfigSUPPORT_OUTGOING_PINGS ) - ICMPPacket_IPv6_t * const pxICMPPacket_IPv6 = ( ICMPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; - #if ipconfigIS_ENABLED( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM ) - pxICMPPacket_IPv6->xICMPHeaderIPv6.usChecksum = 0U; - #endif - ( void ) pxICMPPacket_IPv6; - #else - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported ICMP\n" ) ); - #endif - } - else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_TCP ) - { - #if ipconfigIS_ENABLED( ipconfigUSE_TCP ) - TCPPacket_IPv6_t * const pxTCPPacket_IPv6 = ( TCPPacket_IPv6_t * const ) pxDescriptor->pucEthernetBuffer; - - /* #if defined( niEMAC_STM32HX ) && ipconfigIS_ENABLED( niEMAC_TCP_SEGMENTATION ) - * xTxConfig.PayloadLen = pxDescriptor->xDataLength; - * xTxConfig.TCPHeaderLen = sizeof( pxTCPPacket_IPv6->xTCPHeader ); - * xTxConfig.Attributes |= ETH_TX_PACKETS_FEATURES_TSO; - #endif */ - ( void ) pxTCPPacket_IPv6; - #else - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported TCP\n" ) ); - #endif - } - else if( pxIPPacket_IPv6->xIPHeader.ucNextHeader == ipPROTOCOL_UDP ) - { - UDPPacket_t * const pxUDPPacket_IPv6 = ( UDPPacket_t * const ) pxDescriptor->pucEthernetBuffer; - ( void ) pxUDPPacket_IPv6; - } - #else /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ - FreeRTOS_debug_printf( ( "xNetworkInterfaceOutput: Unsupported IPv6\n" ) ); - #endif /* if ipconfigIS_ENABLED( ipconfigUSE_IPv6 ) */ - } - else if( pxEthHeader->usFrameType == ipARP_FRAME_TYPE ) - { - } ETH_BufferTypeDef xTxBuffer = { @@ -1769,12 +1704,12 @@ static BaseType_t prvAcceptPacket( const NetworkBufferDescriptor_t * const pxDes #if ipconfigIS_ENABLED( ipconfigETHERNET_DRIVER_FILTERS_PACKETS ) { - const ETH_DMADescTypeDef * const ulRxDesc = ( const ETH_DMADescTypeDef * const ) pxEthHandle->RxDescList.RxDesc[ pxEthHandle->RxDescList.RxDescIdx ]; + const ETH_DMADescTypeDef * const pxRxDesc = ( const ETH_DMADescTypeDef * const ) pxEthHandle->RxDescList.RxDesc[ pxEthHandle->RxDescList.RxDescIdx ]; uint32_t ulRxDesc; #ifdef niEMAC_STM32HX - ulRxDesc = ulRxDesc->DESC1; + ulRxDesc = pxRxDesc->DESC1; #elif defined( niEMAC_STM32FX ) - ulRxDesc = ulRxDesc->DESC4; + ulRxDesc = pxRxDesc->DESC4; #endif if( ( ulRxDesc & ETH_IP_HEADER_IPV4 ) != 0 )