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 000000000..a6be0dbdf --- /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 000000000..838406daf --- /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 000000000..d84f05dd4 --- /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); +}