From 335d3e9be5e10b7442c8d310772c9b237e2267af Mon Sep 17 00:00:00 2001 From: Alexei Date: Mon, 10 Apr 2023 08:33:34 +0700 Subject: [PATCH] Added zero copy receiveHandlerTask Added CENTRALISED_DEFERRED_IRQ_HADLING option --- DemoTasks/SimpleTCPEchoServer.c | 4 +- FreeRTOS/source/include/FreeRTOSIPConfig.h | 42 +- FreeRTOS/source/include/IPTraceMacro.h | 6 +- FreeRTOS/source/include/NetworkInterface.h | 422 +-- .../board_family/NetworkInterface.c | 2995 +++++++++-------- RTE/RTOS/FreeRTOSConfig.h | 2 +- RTE/_Target_1/RTE_Components.h | 2 + Test_project_for_GD32107C-EVAL.uvoptx | 129 +- Test_project_for_GD32107C-EVAL.uvprojx | 8 +- main.c | 2 +- 10 files changed, 1884 insertions(+), 1728 deletions(-) diff --git a/DemoTasks/SimpleTCPEchoServer.c b/DemoTasks/SimpleTCPEchoServer.c index acb6ced..806d36e 100644 --- a/DemoTasks/SimpleTCPEchoServer.c +++ b/DemoTasks/SimpleTCPEchoServer.c @@ -159,7 +159,7 @@ struct freertos_sockaddr xClient, xBindAddress; Socket_t xListeningSocket, xConnectedSocket; socklen_t xSize = sizeof( xClient ); static const TickType_t xReceiveTimeOut = portMAX_DELAY; -const BaseType_t xBacklog = 20; +const BaseType_t xBacklog = 1; #if( ipconfigUSE_TCP_WIN == 1 ) @@ -256,7 +256,7 @@ uint8_t *pucRxBuffer; lBytes = FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 ); /* If data was received, echo it back. */ - if( lBytes >= 0 ) + if( lBytes > 0 ) { RF_OUT_ENUM state = -1; int8_t enable = -1; diff --git a/FreeRTOS/source/include/FreeRTOSIPConfig.h b/FreeRTOS/source/include/FreeRTOSIPConfig.h index 86e4786..a1f61a0 100644 --- a/FreeRTOS/source/include/FreeRTOSIPConfig.h +++ b/FreeRTOS/source/include/FreeRTOSIPConfig.h @@ -38,7 +38,7 @@ /* It is not sensible for this macro to have a default value as it is hardware * dependent. */ #define ipconfigBYTE_ORDER pdFREERTOS_LITTLE_ENDIAN -#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 4 +//#define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS 4 #define ipconfigUSE_NETWORK_EVENT_HOOK 1 #define ipconfigUSE_DHCP 1 #define ipconfigUSE_DHCP_HOOK 1 @@ -46,6 +46,46 @@ #define ipconfigMAC_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY ) #define ipconfigDHCP_REGISTER_HOSTNAME 1 #define ipconfigUSE_DNS 1 +#ifndef DEBUG + #warning Define ipconfigWATCHDOG_TIMER() +/* This macro will be called in every loop the IP-task makes. It may be + * replaced by user-code that triggers a watchdog */ + #define ipconfigWATCHDOG_TIMER() +#endif +/* The option 'ipconfigUSE_CALLBACKS' allows to assign specific application + * hooks to a socket. Each hook will be set with a specific socket option: + * + * FREERTOS_SO_TCP_CONN_HANDLER * Callback for (dis) connection events. + * * Supply pointer to 'F_TCP_UDP_Handler_t' + * FREERTOS_SO_TCP_RECV_HANDLER * Callback for receiving TCP data. + * * Supply pointer to 'F_TCP_UDP_Handler_t' + * FREERTOS_SO_TCP_SENT_HANDLER * Callback for sending TCP data. + * * Supply pointer to 'F_TCP_UDP_Handler_t' + * FREERTOS_SO_UDP_RECV_HANDLER * Callback for receiving UDP data. + * * Supply pointer to 'F_TCP_UDP_Handler_t' + * FREERTOS_SO_UDP_SENT_HANDLER * Callback for sending UDP data. + * * Supply pointer to 'F_TCP_UDP_Handler_t' + * + * Note that the call-back functions will run in the IP-task, so very little + * things can be done. Better not to call any networking API, because that + * could easily lead to a deadlock situation. + */ +#define ipconfigUSE_CALLBACKS ( 0 ) + +/* When non-zero, the buffers passed to xNetworkInterfaceOutput() will be passed + * directly to DMA. As soon as sending is ready, the buffers must be released by + * calling vReleaseNetworkBufferAndDescriptor(). */ + +#define ipconfigZERO_COPY_TX_DRIVER ( 0 ) + + +/* When enabled, the network interface will pass the network buffers directly to + * the DMA descriptors. When a packet has been received, the function + * pxPacketBuffer_to_NetworkBuffer() will translate a buffer address to a + * network packet, so it can be passed to the IP-task. */ + +#define ipconfigZERO_COPY_RX_DRIVER ( 1 ) + //#define ipconfigUSE_LLMNR 1 //#define ipconfigUSE_NBNS 1 //#define ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES 1 diff --git a/FreeRTOS/source/include/IPTraceMacro.h b/FreeRTOS/source/include/IPTraceMacro.h index d7add27..bdfcbed 100644 --- a/FreeRTOS/source/include/IPTraceMacro.h +++ b/FreeRTOS/source/include/IPTraceMacro.h @@ -3,16 +3,16 @@ #include -#define iptraceNETWORK_DOWN() FreeRTOS_debug_printf(("[IPTRACE] Network down\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); +//#define iptraceNETWORK_DOWN() FreeRTOS_debug_printf(("[IPTRACE] Network down\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); #define iptraceSENDING_DNS_REQUEST() FreeRTOS_debug_printf(("[IPTRACE] Sending DNS request\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); -#define iptraceSENDING_DHCP_DISCOVER() FreeRTOS_debug_printf(("[IPTRACE] Sending DHCP discover\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); +//#define iptraceSENDING_DHCP_DISCOVER() FreeRTOS_debug_printf(("[IPTRACE] Sending DHCP discover\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); -#define iptraceSENDING_DHCP_REQUEST() FreeRTOS_debug_printf(("[IPTRACE] Sending DHCP request\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); +//#define iptraceSENDING_DHCP_REQUEST() FreeRTOS_debug_printf(("[IPTRACE] Sending DHCP request\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); #define iptraceETHERNET_RX_EVENT_LOST() FreeRTOS_debug_printf(("[IPTRACE] Ethernet rx event lost\nFreeHeapSize = %d\n", xPortGetFreeHeapSize())); diff --git a/FreeRTOS/source/include/NetworkInterface.h b/FreeRTOS/source/include/NetworkInterface.h index 5a45636..8cc9df8 100644 --- a/FreeRTOS/source/include/NetworkInterface.h +++ b/FreeRTOS/source/include/NetworkInterface.h @@ -28,6 +28,7 @@ #ifndef NETWORK_INTERFACE_H #define NETWORK_INTERFACE_H +#ifndef STM32_PORT //#include "FreeRTOS.h" //#include "FreeRTOSIPConfig.h" //#include "stdio.h" @@ -41,301 +42,302 @@ BaseType_t xNetworkInterfaceInitialise( void ); BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,BaseType_t xReleaseAfterSend ); +#else /*STM32_PORT*/ /* *INDENT-ON* */ -///** -// * @brief HAL State structures definition -// */ -// typedef enum -// { -// HAL_ETH_STATE_RESET = 0x00U, /*!< Peripheral not yet Initialized or disabled */ -// HAL_ETH_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ -// HAL_ETH_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ -// HAL_ETH_STATE_BUSY_TX = 0x12U, /*!< Data Transmission process is ongoing */ -// HAL_ETH_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ -// HAL_ETH_STATE_BUSY_TX_RX = 0x32U, /*!< Data Transmission and Reception process is ongoing */ -// HAL_ETH_STATE_BUSY_WR = 0x42U, /*!< Write process is ongoing */ -// HAL_ETH_STATE_BUSY_RD = 0x82U, /*!< Read process is ongoing */ -// HAL_ETH_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ -// HAL_ETH_STATE_ERROR = 0x04U /*!< Reception process is ongoing */ -// } HAL_ETH_StateTypeDef; -// -///** -// * @brief ETH Init Structure definition -// */ +/** + * @brief HAL State structures definition + */ + typedef enum + { + HAL_ETH_STATE_RESET = 0x00U, /*!< Peripheral not yet Initialized or disabled */ + HAL_ETH_STATE_READY = 0x01U, /*!< Peripheral Initialized and ready for use */ + HAL_ETH_STATE_BUSY = 0x02U, /*!< an internal process is ongoing */ + HAL_ETH_STATE_BUSY_TX = 0x12U, /*!< Data Transmission process is ongoing */ + HAL_ETH_STATE_BUSY_RX = 0x22U, /*!< Data Reception process is ongoing */ + HAL_ETH_STATE_BUSY_TX_RX = 0x32U, /*!< Data Transmission and Reception process is ongoing */ + HAL_ETH_STATE_BUSY_WR = 0x42U, /*!< Write process is ongoing */ + HAL_ETH_STATE_BUSY_RD = 0x82U, /*!< Read process is ongoing */ + HAL_ETH_STATE_TIMEOUT = 0x03U, /*!< Timeout state */ + HAL_ETH_STATE_ERROR = 0x04U /*!< Reception process is ongoing */ + } HAL_ETH_StateTypeDef; + +/** + * @brief ETH Init Structure definition + */ -//typedef struct -//{ -// uint32_t AutoNegotiation; /*!< Selects or not the AutoNegotiation mode for the external PHY -// * The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) -// * and the mode (half/full-duplex). -// * This parameter can be a value of @ref ETH_AutoNegotiation */ +typedef struct +{ + uint32_t AutoNegotiation; /*!< Selects or not the AutoNegotiation mode for the external PHY + * The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps) + * and the mode (half/full-duplex). + * This parameter can be a value of @ref ETH_AutoNegotiation */ -// uint32_t Speed; /*!< Sets the Ethernet speed: 10/100 Mbps. -// * This parameter can be a value of @ref ETH_Speed */ + uint32_t Speed; /*!< Sets the Ethernet speed: 10/100 Mbps. + * This parameter can be a value of @ref ETH_Speed */ -// uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode -// * This parameter can be a value of @ref ETH_Duplex_Mode */ + uint32_t DuplexMode; /*!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode + * This parameter can be a value of @ref ETH_Duplex_Mode */ -// uint16_t PhyAddress; /*!< Ethernet PHY address. -// * This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ + uint16_t PhyAddress; /*!< Ethernet PHY address. + * This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ -// uint8_t * MACAddr; /*!< MAC Address of used Hardware: must be pointer on an array of 6 bytes */ + uint8_t * MACAddr; /*!< MAC Address of used Hardware: must be pointer on an array of 6 bytes */ -// uint32_t RxMode; /*!< Selects the Ethernet Rx mode: Polling mode, Interrupt mode. -// * This parameter can be a value of @ref ETH_Rx_Mode */ + uint32_t RxMode; /*!< Selects the Ethernet Rx mode: Polling mode, Interrupt mode. + * This parameter can be a value of @ref ETH_Rx_Mode */ -// uint32_t ChecksumMode; /*!< Selects if the checksum is check by hardware or by software. -// * This parameter can be a value of @ref ETH_Checksum_Mode */ + uint32_t ChecksumMode; /*!< Selects if the checksum is check by hardware or by software. + * This parameter can be a value of @ref ETH_Checksum_Mode */ -// uint32_t MediaInterface; /*!< Selects the media-independent interface or the reduced media-independent interface. -// * This parameter can be a value of @ref ETH_Media_Interface */ -//} ETH_InitTypeDef; + uint32_t MediaInterface; /*!< Selects the media-independent interface or the reduced media-independent interface. + * This parameter can be a value of @ref ETH_Media_Interface */ +} ETH_InitTypeDef; -///** -// * @brief ETH MAC Configuration Structure definition -// */ +/** + * @brief ETH MAC Configuration Structure definition + */ -//typedef struct -//{ -// uint32_t Watchdog; /*!< Selects or not the Watchdog timer -// * When enabled, the MAC allows no more then 2048 bytes to be received. -// * When disabled, the MAC can receive up to 16384 bytes. -// * This parameter can be a value of @ref ETH_Watchdog */ +typedef struct +{ + uint32_t Watchdog; /*!< Selects or not the Watchdog timer + * When enabled, the MAC allows no more then 2048 bytes to be received. + * When disabled, the MAC can receive up to 16384 bytes. + * This parameter can be a value of @ref ETH_Watchdog */ -// uint32_t Jabber; /*!< Selects or not Jabber timer -// * When enabled, the MAC allows no more then 2048 bytes to be sent. -// * When disabled, the MAC can send up to 16384 bytes. -// * This parameter can be a value of @ref ETH_Jabber */ + uint32_t Jabber; /*!< Selects or not Jabber timer + * When enabled, the MAC allows no more then 2048 bytes to be sent. + * When disabled, the MAC can send up to 16384 bytes. + * This parameter can be a value of @ref ETH_Jabber */ -// uint32_t InterFrameGap; /*!< Selects the minimum IFG between frames during transmission. -// * This parameter can be a value of @ref ETH_Inter_Frame_Gap */ + uint32_t InterFrameGap; /*!< Selects the minimum IFG between frames during transmission. + * This parameter can be a value of @ref ETH_Inter_Frame_Gap */ -// uint32_t CarrierSense; /*!< Selects or not the Carrier Sense. -// * This parameter can be a value of @ref ETH_Carrier_Sense */ + uint32_t CarrierSense; /*!< Selects or not the Carrier Sense. + * This parameter can be a value of @ref ETH_Carrier_Sense */ -// uint32_t ReceiveOwn; /*!< Selects or not the ReceiveOwn, -// * ReceiveOwn allows the reception of frames when the TX_EN signal is asserted -// * in Half-Duplex mode. -// * This parameter can be a value of @ref ETH_Receive_Own */ + uint32_t ReceiveOwn; /*!< Selects or not the ReceiveOwn, + * ReceiveOwn allows the reception of frames when the TX_EN signal is asserted + * in Half-Duplex mode. + * This parameter can be a value of @ref ETH_Receive_Own */ -// uint32_t LoopbackMode; /*!< Selects or not the internal MAC MII Loopback mode. -// * This parameter can be a value of @ref ETH_Loop_Back_Mode */ + uint32_t LoopbackMode; /*!< Selects or not the internal MAC MII Loopback mode. + * This parameter can be a value of @ref ETH_Loop_Back_Mode */ -// uint32_t ChecksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. -// * This parameter can be a value of @ref ETH_Checksum_Offload */ + uint32_t ChecksumOffload; /*!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers. + * This parameter can be a value of @ref ETH_Checksum_Offload */ -// uint32_t RetryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, -// * when a collision occurs (Half-Duplex mode). -// * This parameter can be a value of @ref ETH_Retry_Transmission */ + uint32_t RetryTransmission; /*!< Selects or not the MAC attempt retries transmission, based on the settings of BL, + * when a collision occurs (Half-Duplex mode). + * This parameter can be a value of @ref ETH_Retry_Transmission */ -// uint32_t AutomaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping. -// * This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ + uint32_t AutomaticPadCRCStrip; /*!< Selects or not the Automatic MAC Pad/CRC Stripping. + * This parameter can be a value of @ref ETH_Automatic_Pad_CRC_Strip */ -// uint32_t BackOffLimit; /*!< Selects the BackOff limit value. -// * This parameter can be a value of @ref ETH_Back_Off_Limit */ + uint32_t BackOffLimit; /*!< Selects the BackOff limit value. + * This parameter can be a value of @ref ETH_Back_Off_Limit */ -// uint32_t DeferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode). -// * This parameter can be a value of @ref ETH_Deferral_Check */ + uint32_t DeferralCheck; /*!< Selects or not the deferral check function (Half-Duplex mode). + * This parameter can be a value of @ref ETH_Deferral_Check */ -// uint32_t ReceiveAll; /*!< Selects or not all frames reception by the MAC (No filtering). -// * This parameter can be a value of @ref ETH_Receive_All */ + uint32_t ReceiveAll; /*!< Selects or not all frames reception by the MAC (No filtering). + * This parameter can be a value of @ref ETH_Receive_All */ -// uint32_t SourceAddrFilter; /*!< Selects the Source Address Filter mode. -// * This parameter can be a value of @ref ETH_Source_Addr_Filter */ + uint32_t SourceAddrFilter; /*!< Selects the Source Address Filter mode. + * This parameter can be a value of @ref ETH_Source_Addr_Filter */ -// uint32_t PassControlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) -// * This parameter can be a value of @ref ETH_Pass_Control_Frames */ + uint32_t PassControlFrames; /*!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames) + * This parameter can be a value of @ref ETH_Pass_Control_Frames */ -// uint32_t BroadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames. -// * This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ + uint32_t BroadcastFramesReception; /*!< Selects or not the reception of Broadcast Frames. + * This parameter can be a value of @ref ETH_Broadcast_Frames_Reception */ -// uint32_t DestinationAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames. -// * This parameter can be a value of @ref ETH_Destination_Addr_Filter */ + uint32_t DestinationAddrFilter; /*!< Sets the destination filter mode for both unicast and multicast frames. + * This parameter can be a value of @ref ETH_Destination_Addr_Filter */ -// uint32_t PromiscuousMode; /*!< Selects or not the Promiscuous Mode -// * This parameter can be a value of @ref ETH_Promiscuous_Mode */ + uint32_t PromiscuousMode; /*!< Selects or not the Promiscuous Mode + * This parameter can be a value of @ref ETH_Promiscuous_Mode */ -// uint32_t MulticastFramesFilter; /*!< Selects the Multicast Frames filter mode: None/HashTableFilter/PerfectFilter/PerfectHashTableFilter. -// * This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ + uint32_t MulticastFramesFilter; /*!< Selects the Multicast Frames filter mode: None/HashTableFilter/PerfectFilter/PerfectHashTableFilter. + * This parameter can be a value of @ref ETH_Multicast_Frames_Filter */ -// uint32_t UnicastFramesFilter; /*!< Selects the Unicast Frames filter mode: HashTableFilter/PerfectFilter/PerfectHashTableFilter. -// * This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ + uint32_t UnicastFramesFilter; /*!< Selects the Unicast Frames filter mode: HashTableFilter/PerfectFilter/PerfectHashTableFilter. + * This parameter can be a value of @ref ETH_Unicast_Frames_Filter */ -// uint32_t HashTableHigh; /*!< This field holds the higher 32 bits of Hash table. -// * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFF */ + uint32_t HashTableHigh; /*!< This field holds the higher 32 bits of Hash table. + * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFF */ -// uint32_t HashTableLow; /*!< This field holds the lower 32 bits of Hash table. -// * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFF */ + uint32_t HashTableLow; /*!< This field holds the lower 32 bits of Hash table. + * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFFFFFF */ -// uint32_t PauseTime; /*!< This field holds the value to be used in the Pause Time field in the transmit control frame. -// * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFF */ + uint32_t PauseTime; /*!< This field holds the value to be used in the Pause Time field in the transmit control frame. + * This parameter must be a number between Min_Data = 0x0 and Max_Data = 0xFFFF */ -// uint32_t ZeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames. -// * This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ + uint32_t ZeroQuantaPause; /*!< Selects or not the automatic generation of Zero-Quanta Pause Control frames. + * This parameter can be a value of @ref ETH_Zero_Quanta_Pause */ -// uint32_t PauseLowThreshold; /*!< This field configures the threshold of the PAUSE to be checked for -// * automatic retransmission of PAUSE Frame. -// * This parameter can be a value of @ref ETH_Pause_Low_Threshold */ + uint32_t PauseLowThreshold; /*!< This field configures the threshold of the PAUSE to be checked for + * automatic retransmission of PAUSE Frame. + * This parameter can be a value of @ref ETH_Pause_Low_Threshold */ -// uint32_t UnicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 -// * unicast address and unique multicast address). -// * This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ + uint32_t UnicastPauseFrameDetect; /*!< Selects or not the MAC detection of the Pause frames (with MAC Address0 + * unicast address and unique multicast address). + * This parameter can be a value of @ref ETH_Unicast_Pause_Frame_Detect */ -// uint32_t ReceiveFlowControl; /*!< Enables or disables the MAC to decode the received Pause frame and -// * disable its transmitter for a specified time (Pause Time) -// * This parameter can be a value of @ref ETH_Receive_Flow_Control */ + uint32_t ReceiveFlowControl; /*!< Enables or disables the MAC to decode the received Pause frame and + * disable its transmitter for a specified time (Pause Time) + * This parameter can be a value of @ref ETH_Receive_Flow_Control */ -// uint32_t TransmitFlowControl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) -// * or the MAC back-pressure operation (Half-Duplex mode) -// * This parameter can be a value of @ref ETH_Transmit_Flow_Control */ + uint32_t TransmitFlowControl; /*!< Enables or disables the MAC to transmit Pause frames (Full-Duplex mode) + * or the MAC back-pressure operation (Half-Duplex mode) + * This parameter can be a value of @ref ETH_Transmit_Flow_Control */ -// uint32_t VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for -// * comparison and filtering. -// * This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ + uint32_t VLANTagComparison; /*!< Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for + * comparison and filtering. + * This parameter can be a value of @ref ETH_VLAN_Tag_Comparison */ -// uint32_t VLANTagIdentifier; /*!< Holds the VLAN tag identifier for receive frames */ -//} ETH_MACInitTypeDef; + uint32_t VLANTagIdentifier; /*!< Holds the VLAN tag identifier for receive frames */ +} ETH_MACInitTypeDef; -///** -// * @brief ETH DMA Configuration Structure definition -// */ +/** + * @brief ETH DMA Configuration Structure definition + */ -//typedef struct -//{ -// uint32_t DropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames. -// * This parameter can be a value of @ref ETH_Drop_TCP_IP_Checksum_Error_Frame */ +typedef struct +{ + uint32_t DropTCPIPChecksumErrorFrame; /*!< Selects or not the Dropping of TCP/IP Checksum Error Frames. + * This parameter can be a value of @ref ETH_Drop_TCP_IP_Checksum_Error_Frame */ -// uint32_t ReceiveStoreForward; /*!< Enables or disables the Receive store and forward mode. -// * This parameter can be a value of @ref ETH_Receive_Store_Forward */ + uint32_t ReceiveStoreForward; /*!< Enables or disables the Receive store and forward mode. + * This parameter can be a value of @ref ETH_Receive_Store_Forward */ -// uint32_t FlushReceivedFrame; /*!< Enables or disables the flushing of received frames. -// * This parameter can be a value of @ref ETH_Flush_Received_Frame */ + uint32_t FlushReceivedFrame; /*!< Enables or disables the flushing of received frames. + * This parameter can be a value of @ref ETH_Flush_Received_Frame */ -// uint32_t TransmitStoreForward; /*!< Enables or disables Transmit store and forward mode. -// * This parameter can be a value of @ref ETH_Transmit_Store_Forward */ + uint32_t TransmitStoreForward; /*!< Enables or disables Transmit store and forward mode. + * This parameter can be a value of @ref ETH_Transmit_Store_Forward */ -// uint32_t TransmitThresholdControl; /*!< Selects or not the Transmit Threshold Control. -// * This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ + uint32_t TransmitThresholdControl; /*!< Selects or not the Transmit Threshold Control. + * This parameter can be a value of @ref ETH_Transmit_Threshold_Control */ -// uint32_t ForwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames. -// * This parameter can be a value of @ref ETH_Forward_Error_Frames */ + uint32_t ForwardErrorFrames; /*!< Selects or not the forward to the DMA of erroneous frames. + * This parameter can be a value of @ref ETH_Forward_Error_Frames */ -// uint32_t ForwardUndersizedGoodFrames; /*!< Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error -// * and length less than 64 bytes) including pad-bytes and CRC) -// * This parameter can be a value of @ref ETH_Forward_Undersized_Good_Frames */ + uint32_t ForwardUndersizedGoodFrames; /*!< Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error + * and length less than 64 bytes) including pad-bytes and CRC) + * This parameter can be a value of @ref ETH_Forward_Undersized_Good_Frames */ -// uint32_t ReceiveThresholdControl; /*!< Selects the threshold level of the Receive FIFO. -// * This parameter can be a value of @ref ETH_Receive_Threshold_Control */ + uint32_t ReceiveThresholdControl; /*!< Selects the threshold level of the Receive FIFO. + * This parameter can be a value of @ref ETH_Receive_Threshold_Control */ -// uint32_t SecondFrameOperate; /*!< Selects or not the Operate on second frame mode, which allows the DMA to process a second -// * frame of Transmit data even before obtaining the status for the first frame. -// * This parameter can be a value of @ref ETH_Second_Frame_Operate */ + uint32_t SecondFrameOperate; /*!< Selects or not the Operate on second frame mode, which allows the DMA to process a second + * frame of Transmit data even before obtaining the status for the first frame. + * This parameter can be a value of @ref ETH_Second_Frame_Operate */ -// uint32_t AddressAlignedBeats; /*!< Enables or disables the Address Aligned Beats. -// * This parameter can be a value of @ref ETH_Address_Aligned_Beats */ + uint32_t AddressAlignedBeats; /*!< Enables or disables the Address Aligned Beats. + * This parameter can be a value of @ref ETH_Address_Aligned_Beats */ -// uint32_t FixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers. -// * This parameter can be a value of @ref ETH_Fixed_Burst */ + uint32_t FixedBurst; /*!< Enables or disables the AHB Master interface fixed burst transfers. + * This parameter can be a value of @ref ETH_Fixed_Burst */ -// uint32_t RxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction. -// * This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ + uint32_t RxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction. + * This parameter can be a value of @ref ETH_Rx_DMA_Burst_Length */ -// uint32_t TxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction. -// * This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ + uint32_t TxDMABurstLength; /*!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction. + * This parameter can be a value of @ref ETH_Tx_DMA_Burst_Length */ -// uint32_t EnhancedDescriptorFormat; /*!< Enables the enhanced descriptor format. -// * This parameter can be a value of @ref ETH_DMA_Enhanced_descriptor_format */ + uint32_t EnhancedDescriptorFormat; /*!< Enables the enhanced descriptor format. + * This parameter can be a value of @ref ETH_DMA_Enhanced_descriptor_format */ -// uint32_t DescriptorSkipLength; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) -// * This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ + uint32_t DescriptorSkipLength; /*!< Specifies the number of word to skip between two unchained descriptors (Ring mode) + * This parameter must be a number between Min_Data = 0 and Max_Data = 32 */ -// uint32_t DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration. -// * This parameter can be a value of @ref ETH_DMA_Arbitration */ -//} ETH_DMAInitTypeDef; + uint32_t DMAArbitration; /*!< Selects the DMA Tx/Rx arbitration. + * This parameter can be a value of @ref ETH_DMA_Arbitration */ +} ETH_DMAInitTypeDef; -///** -// * @brief ETH DMA Descriptors data structure definition -// */ +/** + * @brief ETH DMA Descriptors data structure definition + */ -//typedef struct -//{ -// volatile uint32_t Status; /*!< Status */ +typedef struct +{ + volatile uint32_t Status; /*!< Status */ -// uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ + uint32_t ControlBufferSize; /*!< Control and Buffer1, Buffer2 lengths */ -// uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ + uint32_t Buffer1Addr; /*!< Buffer1 address pointer */ -// uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ + uint32_t Buffer2NextDescAddr; /*!< Buffer2 or next descriptor address pointer */ -// /*!< Enhanced Ethernet DMA PTP Descriptors */ -// uint32_t ExtendedStatus; /*!< Extended status for PTP receive descriptor */ + /*!< Enhanced Ethernet DMA PTP Descriptors */ + uint32_t ExtendedStatus; /*!< Extended status for PTP receive descriptor */ -// uint32_t Reserved1; /*!< Reserved */ + uint32_t Reserved1; /*!< Reserved */ -// uint32_t TimeStampLow; /*!< Time Stamp Low value for transmit and receive */ + uint32_t TimeStampLow; /*!< Time Stamp Low value for transmit and receive */ -// uint32_t TimeStampHigh; /*!< Time Stamp High value for transmit and receive */ -//} ETH_DMADescTypeDef; + uint32_t TimeStampHigh; /*!< Time Stamp High value for transmit and receive */ +} ETH_DMADescTypeDef; -///** -// * @brief Received Frame Informations structure definition -// */ -//typedef struct -//{ -// ETH_DMADescTypeDef * FSRxDesc; /*!< First Segment Rx Desc */ +/** + * @brief Received Frame Informations structure definition + */ +typedef struct +{ + ETH_DMADescTypeDef * FSRxDesc; /*!< First Segment Rx Desc */ -// ETH_DMADescTypeDef * LSRxDesc; /*!< Last Segment Rx Desc */ + ETH_DMADescTypeDef * LSRxDesc; /*!< Last Segment Rx Desc */ -// uint32_t SegCount; /*!< Segment count */ + uint32_t SegCount; /*!< Segment count */ -// uint32_t length; /*!< Frame length */ + uint32_t length; /*!< Frame length */ -// uint32_t buffer; /*!< Frame buffer */ -//} ETH_DMARxFrameInfos; + uint32_t buffer; /*!< Frame buffer */ +} ETH_DMARxFrameInfos; -//#define ETH_TypeDef void -///** -// * @brief ETH Handle Structure definition -// */ +#define ETH_TypeDef void +/** + * @brief ETH Handle Structure definition + */ -//typedef struct -//{ -// ETH_TypeDef * Instance; /*!< Register base address */ +typedef struct +{ + ETH_TypeDef * Instance; /*!< Register base address */ -// ETH_InitTypeDef Init; /*!< Ethernet Init Configuration */ + ETH_InitTypeDef Init; /*!< Ethernet Init Configuration */ -// uint32_t LinkStatus; /*!< Ethernet link status */ + uint32_t LinkStatus; /*!< Ethernet link status */ -// ETH_DMADescTypeDef * RxDesc; /*!< Rx descriptor to Get */ + ETH_DMADescTypeDef * RxDesc; /*!< Rx descriptor to Get */ -// ETH_DMADescTypeDef * TxDesc; /*!< Tx descriptor to Set */ + ETH_DMADescTypeDef * TxDesc; /*!< Tx descriptor to Set */ -// ETH_DMARxFrameInfos RxFrameInfos; /*!< last Rx frame infos */ + ETH_DMARxFrameInfos RxFrameInfos; /*!< last Rx frame infos */ -// volatile HAL_ETH_StateTypeDef State; /*!< ETH communication state */ + volatile HAL_ETH_StateTypeDef State; /*!< ETH communication state */ -// HAL_LockTypeDef Lock; /*!< ETH Lock */ -//} ETH_HandleTypeDef; -///* INTERNAL API FUNCTIONS. */ -//BaseType_t xNetworkInterfaceInitialise( void ); -//BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, -// BaseType_t xReleaseAfterSend ); + HAL_LockTypeDef Lock; /*!< ETH Lock */ +} ETH_HandleTypeDef; +/* INTERNAL API FUNCTIONS. */ +BaseType_t xNetworkInterfaceInitialise( void ); +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t xReleaseAfterSend ); -///* The following function is defined only when BufferAllocation_1.c is linked in the project. */ -//void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ); +/* The following function is defined only when BufferAllocation_1.c is linked in the project. */ +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ); -///* The following function is defined only when BufferAllocation_1.c is linked in the project. */ -//BaseType_t xGetPhyLinkStatus( void ); - -///* *INDENT-OFF* */ -//#ifdef __cplusplus -// } /* extern "C" */ -//#endif -///* *INDENT-ON* */ +/* The following function is defined only when BufferAllocation_1.c is linked in the project. */ +BaseType_t xGetPhyLinkStatus( void ); +/* *INDENT-OFF* */ +#ifdef __cplusplus + } /* extern "C" */ +#endif +/* *INDENT-ON* */ +#endif /*STM32_PORT*/ #endif /* NETWORK_INTERFACE_H */ diff --git a/FreeRTOS/source/portable/NetworkInterface/board_family/NetworkInterface.c b/FreeRTOS/source/portable/NetworkInterface/board_family/NetworkInterface.c index c8d1321..1c8499b 100644 --- a/FreeRTOS/source/portable/NetworkInterface/board_family/NetworkInterface.c +++ b/FreeRTOS/source/portable/NetworkInterface/board_family/NetworkInterface.c @@ -55,6 +55,8 @@ * */ +#ifndef STM32_PORT + /* Standard includes. */ #include #include @@ -82,9 +84,12 @@ //#ifdef RTE_Drivers_PHY_DP83848C /* Driver PHY DP83848C */ - +#ifdef CENTRALISED_DEFERRED_IRQ_HADLING static void receiveHandlerTask( void *pvParameters ); static TaskHandle_t receiveHandler = NULL; +#else /*CENTRALISED_DEFERRED_IRQ_HADLING*/ +void PendedReceiveHandler( void *pvParameter1, uint32_t ulParameter2 ); +#endif static ARM_ETH_MAC_ADDR own_mac_address ;//device mac adress stores here. MSB first static ARM_DRIVER_ETH_MAC *mac; @@ -103,12 +108,18 @@ extern TaskHandle_t vTaskHelloWorld_Handle, vTaskToggleLed_Handle; */ void ENET_IRQHandler(void) { - portBASE_TYPE pxHigherPriorityTaskWoken = pdFALSE; + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RS)) { enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR); - vTaskNotifyGiveFromISR(receiveHandler, &pxHigherPriorityTaskWoken ); +#ifdef CENTRALISED_DEFERRED_IRQ_HADLING + vTaskNotifyGiveFromISR(receiveHandler, &xHigherPriorityTaskWoken ); +#else /*CENTRALISED_DEFERRED_IRQ_HADLING*/ + xTimerPendFunctionCallFromISR(PendedReceiveHandler, NULL, NULL, &xHigherPriorityTaskWoken ); +#endif /*CENTRALISED_DEFERRED_IRQ_HADLING*/ } + #ifdef DEBUG_RBU_IRQ if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RBU)) { @@ -128,10 +139,7 @@ void ENET_IRQHandler(void) vTaskNotifyGiveIndexedFromISR(vTaskHelloWorld_Handle, 1, &pxHigherPriorityTaskWoken ); } #endif - if( pxHigherPriorityTaskWoken == pdTRUE) - { - taskYIELD(); - } + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } /** @@ -507,9 +515,9 @@ int32_t ARM_ETH_MAC_PHY_Write (uint8_t phy_addr, uint8_t reg_addr, uint16_t data void ethernet_mac_notify (uint32_t event) { switch (event) { case ARM_ETH_MAC_EVENT_RX_FRAME: - /*received frame,call receive fuction*/ - //led1_toggle(); - xTaskNotifyGive( receiveHandler ); + /*received frame,call receive fuction*/ + //xTaskNotifyGive( receiveHandler ); + break; case ARM_ETH_MAC_EVENT_TX_FRAME: @@ -618,12 +626,10 @@ int32_t macIntialise(void) BaseType_t xNetworkInterfaceInitialise( void ) { static ARM_ETH_LINK_INFO info; - if (NULL == receiveHandler) - { - xTaskCreate( receiveHandlerTask, "receiveHandlerTask", 1000, NULL, tskIDLE_PRIORITY + 1, &receiveHandler ); - } + BaseType_t xResult = pdFALSE; - if(macIntialise() == ARM_DRIVER_OK && phyIntialise() ==ARM_DRIVER_OK){ + if(macIntialise() == ARM_DRIVER_OK && phyIntialise() == ARM_DRIVER_OK){ + ARM_ETH_LINK_STATE link = Driver_ETH_PHY0.GetLinkState (); while(link != ARM_ETH_LINK_UP){ @@ -638,14 +644,24 @@ BaseType_t xNetworkInterfaceInitialise( void ) mac->Control(ARM_ETH_MAC_CONTROL_TX, 1); mac->Control(ARM_ETH_MAC_CONTROL_RX, 1); -#warning "mac->Control(0x17, 0x23); check if this configuration fixes DP83848 Elasticity buffer problem. Refer to https://habr.com/ru/post/682172/" + #warning "mac->Control(0x17, 0x23); check if this configuration fixes DP83848 Elasticity buffer problem. Refer to https://habr.com/ru/post/682172/" mac->Control(REG_RBR, RBR_RMII_MODE | RBR_ELAST_BUF); - return pdPASS; - } - else{ - //error - return pdFALSE; +#ifdef CENTRALISED_DEFERRED_IRQ_HADLING + if (NULL == receiveHandler) + { + xTaskCreate( receiveHandlerTask, "receiveHandlerTask", 1000, NULL, tskIDLE_PRIORITY + 1, &receiveHandler ); + } + if ( receiveHandler != NULL) + xResult = pdPASS; + else + FreeRTOS_debug_printf(("[NETWORK_INTERFACE] Failed to create receiveHandlerTask()\n")); +#else /* CENTRALISED_DEFERRED_IRQ_HADLING */ + xResult = pdPASS; +#endif /* CENTRALISED_DEFERRED_IRQ_HADLING */ + }else{ + FreeRTOS_debug_printf(("[NETWORK_INTERFACE] Failed macIntialise() or phyIntialise()\n")); } + return xResult; } /*-----------------------------------------------------------*/ @@ -688,12 +704,37 @@ BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescript return pdTRUE; } -#else -/*zero copy method here*/ +#else /*( ipconfigZERO_COPY_TX_DRIVER == 0)*/ +#warning ipconfigZERO_COPY_TX_DRIVER==1 +/*the Simple network interfaces ,just use Ethernet peripheral driver library functions to copy +data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer.*/ +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor,BaseType_t xReleaseAfterSend ){ + /* Simple network interfaces (as opposed to more efficient zero copy network + interfaces) just use Ethernet peripheral driver library functions to copy + data from the FreeRTOS+TCP buffer into the peripheral driver's own buffer. + This example assumes SendData() is a peripheral driver library function that + takes a pointer to the start of the data to be sent and the length of the + data to be sent as two separate parameters. The start of the data is located + by pxDescriptor->pucEthernetBuffer. The length of the data is located + by pxDescriptor->xDataLength. */ + sendData( pxDescriptor->pucEthernetBuffer, pxDescriptor->xDataLength ); -#endif + /* Call the standard trace macro to log the send event. */ + iptraceNETWORK_INTERFACE_TRANSMIT(); + + if( xReleaseAfterSend != pdFALSE ) + { + /* It is assumed SendData() copies the data out of the FreeRTOS+TCP Ethernet + buffer. The Ethernet buffer is therefore no longer needed, and must be + freed for re-use. */ + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + + return pdTRUE; +} +#endif /*( ipconfigZERO_COPY_TX_DRIVER == 0)*/ /*-----------------------------------------------------------*/ - +#ifdef CENTRALISED_DEFERRED_IRQ_HADLING /*receive data func , will be notify after ARM_ETH_MAC_EVENT_RX_FRAME event*/ #if (ipconfigZERO_COPY_RX_DRIVER==0) static void receiveHandlerTask( void *pvParameters ){ @@ -770,1375 +811,1553 @@ static void receiveHandlerTask( void *pvParameters ){ } } } + +#else /*(ipconfigZERO_COPY_RX_DRIVER==0)*/ +#warning ipconfigZERO_COPY_RX_DRIVER==1 + /* The deferred interrupt handler is a standard RTOS task. FreeRTOS's centralised +deferred interrupt handling capabilities can also be used - however for additional +speed use BufferAllocation_1.c to perform the entire operation in the interrupt +handler. */ +typedef enet_descriptors_struct DMADescriptor_t; +extern enet_descriptors_struct *dma_current_rxdesc; +static void receiveHandlerTask( void *pvParameters ) +{ +NetworkBufferDescriptor_t *pxDescriptor; +size_t xBytesReceived; +DMADescriptor_t *pxDMARxDescriptor; +uint8_t *pucTemp; +/* Used to indicate that xSendEventStructToIPTask() is being called because +of an Ethernet receive event. */ +IPStackEvent_t xRxEvent; + + for( ;; ) + { + /* Wait for the Ethernet MAC interrupt to indicate that another packet + has been received. The task notification is used in a similar way to a + counting semaphore to count Rx events, but is a lot more efficient than + a semaphore. */ + ulTaskNotifyTake( pdFALSE, portMAX_DELAY ); + + /* This example assumes GetNextRxDescriptor() is an Ethernet MAC driver + library function that returns a pointer to the DMA descriptor (of type + DMADescriptor_t again) that references the Ethernet buffer containing the + received data. */ + pxDMARxDescriptor = (DMADescriptor_t *)enet_current_desc_address_get(ENET_RX_CURRENT_DESC);//(void*)dma_current_rxdesc-> buffer2_next_desc_addr;//GetNextRxDescriptor(); + + /* Allocate a new network buffer descriptor that references an Ethernet + frame large enough to hold the maximum network packet size (as defined + in the FreeRTOSIPConfig.h header file). */ + pxDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, 0 ); + + /* Copy the pointer to the newly allocated Ethernet frame to a temporary + variable. */ + pucTemp = pxDescriptor->pucEthernetBuffer; + + /* This example assumes that the DMADescriptor_t type has a member + called pucEthernetBuffer that points to the Ethernet buffer containing + the received data, and a member called xDataLength that holds the length + of the received data. Update the newly allocated network buffer descriptor + to point to the Ethernet buffer that contains the received data. */ + pxDescriptor->pucEthernetBuffer = (uint8_t*)enet_desc_information_get(pxDMARxDescriptor, RXDESC_BUFFER_1_ADDR);//pxDMARxDescriptor->pucEthernetBuffer; + pxDescriptor->xDataLength = enet_rxframe_size_get();//enet_desc_information_get(pxDMARxDescriptor, RXDESC_FRAME_LENGTH);////pxDMARxDescriptor->xDataLength; + + /* Update the Ethernet Rx DMA descriptor to point to the newly allocated + Ethernet buffer. */ + pxDMARxDescriptor->buffer1_addr = (uint32_t)pucTemp; //pxDMARxDescriptor->puxEthernetBuffer = pucTemp; + + /* A pointer to the descriptor is stored at the front of the buffer, so + swap these too. */ + *( ( NetworkBufferDescriptor_t ** ) + ( pxDescriptor->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxDescriptor; + + *( ( NetworkBufferDescriptor_t ** ) + ( pxDMARxDescriptor->buffer1_addr - ipBUFFER_PADDING ) ) = (NetworkBufferDescriptor_t*)pxDMARxDescriptor;//( pxDMARxDescriptor->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxDMARxDescriptor; + + /* + * The network buffer descriptor now points to the Ethernet buffer that + * contains the received data, and the Ethernet DMA descriptor now points + * to a newly allocated (and empty) Ethernet buffer ready to receive more + * data. No data was copied. Only pointers to data were swapped. + * + * THE REST OF THE RECEIVE HANDLER FUNCTION FOLLOWS THE EXAMPLE PROVIDED + * FOR THE SIMPLE ETHERNET INTERFACE IMPLEMENTATION, whereby the network + * buffer descriptor is sent to the TCP/IP on the network event queue. + */ + + + + /* See if the data contained in the received Ethernet frame needs + to be processed. NOTE! It might be possible to do this in + the interrupt service routine itself, which would remove the need + to unblock this task for packets that don't need processing. */ + if( eConsiderFrameForProcessing( pxDescriptor->pucEthernetBuffer ) + == eProcessBuffer ) + { + /* The event about to be sent to the TCP/IP is an Rx event. */ + xRxEvent.eEventType = eNetworkRxEvent; + + /* pvData is used to point to the network buffer descriptor that + references the received data. */ + xRxEvent.pvData = ( void * ) pxDescriptor; + + /* Send the data to the TCP/IP stack. */ + if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ) + { + /* The buffer could not be sent to the IP task so the buffer + must be released. */ + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + + /* Make a call to the standard trace macro to log the + occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + } + else + { + /* The message was successfully sent to the TCP/IP stack. + Call the standard trace macro to log the occurrence. */ + iptraceNETWORK_INTERFACE_RECEIVE(); + } + } + else + { + /* The Ethernet frame can be dropped, but the Ethernet buffer + must be released. */ + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + } +} +#endif /*(ipconfigZERO_COPY_RX_DRIVER==0)*/ +#else /* CENTRALISED_DEFERRED_IRQ_HADLING*/ +void PendedReceiveHandler( void *pvParameter1, uint32_t ulParameter2 ) +{ + NetworkBufferDescriptor_t *receiveBufferDescriptor; + size_t xBytesReceived; + /* Used to indicate that xSendEventStructToIPTask() is being called becauseof an Ethernet receive event. */ + IPStackEvent_t xRxEvent; + + xBytesReceived = mac->GetRxFrameSize(); + if( xBytesReceived > 0 ){ + /* Allocate a network buffer descriptor that points to a buffer + large enough to hold the received frame. As this is the simple + rather than efficient example the received data will just be copied + into this buffer. */ + receiveBufferDescriptor = pxGetNetworkBufferWithDescriptor( xBytesReceived, 0 ); + if( receiveBufferDescriptor != NULL ){ + /* pxBufferDescriptor->pucEthernetBuffer now points to an Ethernet + buffer large enough to hold the received data. Copy the + received data into pcNetworkBuffer->pucEthernetBuffer. Here it + is assumed ReceiveData() is a peripheral driver function that + copies the received data into a buffer passed in as the function's + parameter. Remember! While is is a simple robust technique - + it is not efficient. An example that uses a zero copy technique + is provided further down this page. */ + mac->ReadFrame(receiveBufferDescriptor->pucEthernetBuffer,xBytesReceived); + receiveBufferDescriptor->xDataLength = xBytesReceived; + + /* See if the data contained in the received Ethernet frame needs + to be processed. NOTE! It is preferable to do this in + the interrupt service routine itself, which would remove the need + to unblock this task for packets that don't need processing. */ + if( eConsiderFrameForProcessing( receiveBufferDescriptor->pucEthernetBuffer )== eProcessBuffer ){ + /* The event about to be sent to the TCP/IP is an Rx event. */ + xRxEvent.eEventType = eNetworkRxEvent; + + /* pvData is used to point to the network buffer descriptor that + now references the received data. */ + xRxEvent.pvData = ( void * ) receiveBufferDescriptor; + + /* Send the data to the TCP/IP stack. */ + if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE ){ + /* The buffer could not be sent to the IP task so the buffer must be released. */ + vReleaseNetworkBufferAndDescriptor( receiveBufferDescriptor ); + + /* Make a call to the standard trace macro to log the occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + }else{ + /* The message was successfully sent to the TCP/IP stack. + Call the standard trace macro to log the occurrence. */ + iptraceNETWORK_INTERFACE_RECEIVE(); + } + }else{ + /* The Ethernet frame can be dropped, but the Ethernet buffer + must be released. */ + vReleaseNetworkBufferAndDescriptor( receiveBufferDescriptor ); + } + + }else{ + /* The event was lost because a network buffer was not available. + Call the standard trace macro to log the occurrence. */ + iptraceETHERNET_RX_EVENT_LOST(); + } + } +} +#endif /* CENTRALISED_DEFERRED_IRQ_HADLING*/ +#else /*STM32_PORT*/ +/* + * FreeRTOS+TCP V3.1.0 + * 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 + */ + +/***************************************************************************** +* Note: This file is Not! to be used as is. The purpose of this file is to provide +* a template for writing a network interface. Each network interface will have to provide +* concrete implementations of the functions in this file. +* +* See the following URL for an explanation of this file and its functions: +* https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Porting.html +* +*****************************************************************************/ + +/* 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_Sockets.h" +#include "FreeRTOS_IP_Private.h" +#include "FreeRTOS_DNS.h" +#include "FreeRTOS_ARP.h" +#include "NetworkBufferManagement.h" +#include "NetworkInterface.h" +#include "phyHandling.h" + +//#include "stm32fxx_hal_eth.h" + +/*#include "Driver_ETH.h" +#include "Driver_ETH_MAC.h" +#include "Driver_ETH_PHY.h"*/ +/* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet + * driver will filter incoming packets and only pass the stack those packets it + * considers need processing. */ +#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer #else -/*zero copy method here*/ - + #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) #endif -///* -// * FreeRTOS+TCP V3.1.0 -// * 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 -// */ - -///***************************************************************************** -//* Note: This file is Not! to be used as is. The purpose of this file is to provide -//* a template for writing a network interface. Each network interface will have to provide -//* concrete implementations of the functions in this file. -//* -//* See the following URL for an explanation of this file and its functions: -//* https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Porting.html -//* -//*****************************************************************************/ - -///* 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_Sockets.h" -//#include "FreeRTOS_IP_Private.h" -//#include "FreeRTOS_DNS.h" -//#include "FreeRTOS_ARP.h" -//#include "NetworkBufferManagement.h" -//#include "NetworkInterface.h" -//#include "phyHandling.h" - -////#include "stm32fxx_hal_eth.h" - -///*#include "Driver_ETH.h" -//#include "Driver_ETH_MAC.h" -//#include "Driver_ETH_PHY.h"*/ -///* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet -// * driver will filter incoming packets and only pass the stack those packets it -// * considers need processing. */ -//#if ( ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0 ) -// #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer -//#else -// #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) ) -//#endif - - -//BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, -// BaseType_t xReleaseAfterSend ) -//{ -// /* FIX ME. */ -// return pdFALSE; -//} - -//void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) -//{ -// /* FIX ME. */ -//} - -//BaseType_t xGetPhyLinkStatus( void ) -//{ -// /* FIX ME. */ -// return pdFALSE; -//} - - - - -///* ST includes. */ -//#if defined( GD32F10X_CL ) -// #include "gd32f10x_enet.h" -//#elif defined( STM32F7xx ) -// #include "stm32f7xx_hal.h" -// #define CACHE_LINE_SIZE 32u -//#elif defined( STM32F4xx ) -// #include "stm32f4xx_hal.h" -//#elif defined( STM32F2xx ) -// #include "stm32f2xx_hal.h" -//#elif defined( STM32F1xx ) -// #include "stm32f1xx_hal.h" -//#elif !defined( _lint ) /* Lint does not like an #error */ -// #error What part? -//#endif /* if defined( GD32F10X_CL ) */ - - -///* Interrupt events to process. Currently only the Rx event is processed -// * although code for other events is included to allow for possible future -// * expansion. */ -//#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 ) - -///* Calculate the maximum packet size that the DMA can receive. */ -//#define EMAC_DMA_BUFFER_SIZE ( ( uint32_t ) ( ETH_MAX_PACKET_SIZE - ipBUFFER_PADDING ) ) - -//#define ETH_DMA_ALL_INTS \ -// ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | \ -// ETH_DMA_IT_AIS | ETH_DMA_IT_ER | ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | \ -// ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | ETH_DMA_IT_TU | \ -// ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T ) - -//#ifndef NETWORK_BUFFER_HEADER_SIZE -// #define NETWORK_BUFFER_HEADER_SIZE ( ipBUFFER_PADDING ) -//#endif - -//#ifndef niEMAC_HANDLER_TASK_PRIORITY -// #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1 -//#endif - -//#if ( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) -// #warning Consider enabling checksum offloading -//#endif - -//#ifndef niDESCRIPTOR_WAIT_TIME_MS -// #define niDESCRIPTOR_WAIT_TIME_MS 250uL -//#endif - -///* -// * Most users will want a PHY that negotiates about -// * the connection properties: speed, dmix and duplex. -// * On some rare cases, you want to select what is being -// * advertised, properties like MDIX and duplex. -// */ - -//#if !defined( ipconfigETHERNET_AN_ENABLE ) -// /* Enable auto-negotiation */ -// #define ipconfigETHERNET_AN_ENABLE 1 -//#endif - -//#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE ) -// #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1 -//#endif - -//#if ( ipconfigETHERNET_AN_ENABLE == 0 ) - -///* -// * The following three defines are only used in case there -// * is no auto-negotiation. -// */ -// #if !defined( ipconfigETHERNET_CROSSED_LINK ) -// #define ipconfigETHERNET_CROSSED_LINK 1 -// #endif - -// #if !defined( ipconfigETHERNET_USE_100MB ) -// #define ipconfigETHERNET_USE_100MB 1 -// #endif - -// #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX ) -// #define ipconfigETHERNET_USE_FULL_DUPLEX 1 -// #endif -//#endif /* ipconfigETHERNET_AN_ENABLE == 0 */ - -///* Default the size of the stack used by the EMAC deferred handler task to twice -// * the size of the stack used by the idle task - but allow this to be overridden in -// * FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ -//#ifndef configEMAC_TASK_STACK_SIZE -// #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE ) -//#endif - -///* Two choices must be made: RMII versus MII, -// * and the index of the PHY in use ( between 0 and 31 ). */ -//#ifndef ipconfigUSE_RMII -// #ifdef GD32F10X_CL -// #define ipconfigUSE_RMII 1 -// #warning Using RMII, make sure if this is correct -// #else -// #define ipconfigUSE_RMII 0 -// #warning Using MII, make sure if this is correct -// #endif /* GD32F10X_CL */ -//#endif /* ipconfigUSE_RMII */ - -//typedef enum -//{ -// eMACInit, /* Must initialise MAC. */ -// eMACPass, /* Initialisation was successful. */ -// eMACFailed, /* Initialisation failed. */ -//} eMAC_INIT_STATUS_TYPE; - -//static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; - -///*-----------------------------------------------------------*/ - -///* -// * A deferred interrupt handler task that processes -// */ -//static void prvEMACHandlerTask( void * pvParameters ); - -///* -// * Force a negotiation with the Switch or Router and wait for LS. -// */ -//static void prvEthernetUpdateConfig( BaseType_t xForce ); - -///* -// * See if there is a new packet and forward it to the IP-task. -// */ -//static BaseType_t prvNetworkInterfaceInput( void ); - -//#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) - -///* -// * For LLMNR, an extra MAC-address must be configured to -// * be able to receive the multicast messages. -// */ -// static void prvMACAddressConfig( ETH_HandleTypeDef * heth, -// uint32_t ulIndex, -// uint8_t * Addr ); -//#endif - -///* -// * Check if a given packet should be accepted. -// */ -//static BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ); - -///* -// * Initialise the TX descriptors. -// */ -//static void prvDMATxDescListInit( void ); - -///* -// * Initialise the RX descriptors. -// */ -//static void prvDMARxDescListInit( void ); - -///* After packets have been sent, the network -// * buffers will be released. */ -//static void vClearTXBuffers( void ); - -///*-----------------------------------------------------------*/ - -//#if ( ipconfigUSE_LLMNR == 1 ) -// static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; -//#endif - -//static EthernetPhy_t xPhyObject; - -///* Ethernet handle. */ -//static ETH_HandleTypeDef xETH; - -///* xTXDescriptorSemaphore is a counting semaphore with -// * a maximum count of ETH_TXBUFNB, which is the number of -// * DMA TX descriptors. */ -//static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; - -///* -// * Note: it is advised to define both -// * -// * #define ipconfigZERO_COPY_RX_DRIVER 1 -// * #define ipconfigZERO_COPY_TX_DRIVER 1 -// * -// * The method using memcpy is slower and probably uses more RAM memory. -// * The possibility is left in the code just for comparison. -// * -// * It is advised to define ETH_TXBUFNB at least 4. Note that no -// * TX buffers are allocated in a zero-copy driver. -// */ -///* MAC buffers: ---------------------------------------------------------*/ - -///* Put the DMA descriptors in '.first_data'. -// * This is important for STM32F7, which has an L1 data cache. -// * The first 64KB of the SRAM is not cached. -// * See README.TXT in this folder. */ - -///* Ethernet Rx MA Descriptor */ -//__attribute__( ( aligned( 32 ) ) ) -//#if defined( STM32F7xx ) -// __attribute__( ( section( ".first_data" ) ) ) -//#endif -//ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ]; - -//#if ( ipconfigZERO_COPY_RX_DRIVER == 0 ) -// /* Ethernet Receive Buffer */ -// __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; -//#endif - -///* Ethernet Tx DMA Descriptor */ -//__attribute__( ( aligned( 32 ) ) ) -//#if defined( STM32F7xx ) -// __attribute__( ( section( ".first_data" ) ) ) -//#endif -//ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ]; - -//#if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) -// /* Ethernet Transmit Buffer */ -// __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; -//#endif - -///* DMATxDescToClear points to the next TX DMA descriptor -// * that must be cleared by vClearTXBuffers(). */ -//static __IO ETH_DMADescTypeDef * DMATxDescToClear; - -///* Holds the handle of the task used as a deferred interrupt processor. The -// * handle is used so direct notifications can be sent to the task for all EMAC/DMA -// * related interrupts. */ -//static TaskHandle_t xEMACTaskHandle = NULL; - -///* For local use only: describe the PHY's properties: */ -//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 ) */ - -// #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 -//}; - -///*-----------------------------------------------------------*/ - -//void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) -//{ -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; - -// ( void ) heth; - -// /* Pass an RX-event and wakeup the prvEMACHandlerTask. */ -// if( xEMACTaskHandle != NULL ) -// { -// xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &( xHigherPriorityTaskWoken ) ); -// portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -// } -//} -///*-----------------------------------------------------------*/ - -//void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) -//{ -// BaseType_t xHigherPriorityTaskWoken = pdFALSE; - -// ( void ) heth; - -// /* Pass a TX-event and wakeup the prvEMACHandlerTask. */ -// if( xEMACTaskHandle != NULL ) -// { -// xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &( xHigherPriorityTaskWoken ) ); -// portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -// } -//} -///*-----------------------------------------------------------*/ - -//static void vClearTXBuffers() -//{ -// __IO ETH_DMADescTypeDef * txLastDescriptor = xETH.TxDesc; -// size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); - -// #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) -// NetworkBufferDescriptor_t * pxNetworkBuffer; -// uint8_t * ucPayLoad; -// #endif - -// /* This function is called after a TX-completion interrupt. -// * It will release each Network Buffer used in xNetworkInterfaceOutput(). -// * 'uxCount' represents the number of descriptors given to DMA for transmission. -// * After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */ -// while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) ) -// { -// if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) ) -// { -// break; -// } - -// #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) -// { -// ucPayLoad = ( uint8_t * ) DMATxDescToClear->Buffer1Addr; - -// if( ucPayLoad != NULL ) -// { -// pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad ); - -// if( pxNetworkBuffer != NULL ) -// { -// vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); -// } - -// DMATxDescToClear->Buffer1Addr = ( uint32_t ) 0u; -// } -// } -// #endif /* ipconfigZERO_COPY_TX_DRIVER */ - -// DMATxDescToClear = ( ETH_DMADescTypeDef * ) ( DMATxDescToClear->Buffer2NextDescAddr ); - -// uxCount--; -// /* Tell the counting semaphore that one more TX descriptor is available. */ -// xSemaphoreGive( xTXDescriptorSemaphore ); -// } -//} -///*-----------------------------------------------------------*/ - -//BaseType_t xNetworkInterfaceInitialise( void ) -//{ -// HAL_StatusTypeDef hal_eth_init_status; -// BaseType_t xResult; - -// #if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) -// BaseType_t xMACEntry = ETH_MAC_ADDRESS1; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ -// #endif - -// if( xMacInitStatus == eMACInit ) -// { -// xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB ); - -// if( xTXDescriptorSemaphore == NULL ) -// { -// xMacInitStatus = eMACFailed; -// } -// else -// { -// /* Initialise ETH */ - -// xETH.Instance = ETH; -// xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; -// xETH.Init.Speed = ETH_SPEED_100M; -// xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; -// /* Value of PhyAddress doesn't matter, will be probed for. */ -// xETH.Init.PhyAddress = 0; - -// xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); -// xETH.Init.RxMode = ETH_RXINTERRUPT_MODE; - -// #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) -// { -// /* using the ETH_CHECKSUM_BY_HARDWARE option: -// * both the IP and the protocol checksums will be calculated -// * by the peripheral. */ -// xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; -// } -// #else -// { -// xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; -// } -// #endif - -// #if ( ipconfigUSE_RMII != 0 ) -// { -// xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; -// } -// #else -// { -// xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; -// } -// #endif /* ipconfigUSE_RMII */ - -// hal_eth_init_status = HAL_ETH_Init( &xETH ); - -// /* Only for inspection by debugger. */ -// ( void ) hal_eth_init_status; - -// /* Set the TxDesc and RxDesc pointers. */ -// xETH.TxDesc = DMATxDscrTab; -// xETH.RxDesc = DMARxDscrTab; - -// /* Make sure that all unused fields are cleared. */ -// memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) ); -// memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) ); - -// /* Initialize Tx Descriptors list: Chain Mode */ -// DMATxDescToClear = DMATxDscrTab; - -// /* Initialise TX-descriptors. */ -// prvDMATxDescListInit(); - -// /* Initialise RX-descriptors. */ -// prvDMARxDescListInit(); - -// #if ( ipconfigUSE_MDNS == 1 ) -// { -// /* Program the MDNS address. */ -// prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xMDNS_MACAddressIPv4 ); -// xMACEntry += 8; -// } -// #endif -// #if ( ipconfigUSE_LLMNR == 1 ) -// { -// /* Program the LLMNR address. */ -// prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xLLMNR_MACAddress ); -// xMACEntry += 8; -// } -// #endif - -// /* Force a negotiation with the Switch or Router and wait for LS. */ -// prvEthernetUpdateConfig( pdTRUE ); - -// /* The deferred interrupt handler task is created at the highest -// * possible priority to ensure the interrupt handler can return directly -// * to it. The task's handle is stored in xEMACTaskHandle so interrupts can -// * notify the task when there is something to process. */ -// if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS ) -// { -// /* The xTXDescriptorSemaphore and the task are created successfully. */ -// xMacInitStatus = eMACPass; -// } -// else -// { -// xMacInitStatus = eMACFailed; -// } -// } -// } /* if( xMacInitStatus == eMACInit ) */ - -// if( xMacInitStatus != eMACPass ) -// { -// /* EMAC initialisation failed, return pdFAIL. */ -// xResult = pdFAIL; -// } -// else -// { -// if( xPhyObject.ulLinkStatusMask != 0U ) -// { -// xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS; -// xResult = pdPASS; -// FreeRTOS_printf( ( "Link Status is high\n" ) ); -// } -// else -// { -// /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running -// * and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */ -// xResult = pdFAIL; -// } -// } - -// /* When returning non-zero, the stack will become active and -// * start DHCP (in configured) */ -// return xResult; -//} -///*-----------------------------------------------------------*/ - -//static void prvDMATxDescListInit() -//{ -// ETH_DMADescTypeDef * pxDMADescriptor; -// BaseType_t xIndex; - -// /* Get the pointer on the first member of the descriptor list */ -// pxDMADescriptor = DMATxDscrTab; - -// /* Fill each DMA descriptor with the right values */ -// for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ ) -// { -// /* Set Second Address Chained bit */ -// pxDMADescriptor->Status = ETH_DMATXDESC_TCH; - -// #if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) -// { -// /* Set Buffer1 address pointer */ -// pxDMADescriptor->Buffer1Addr = ( uint32_t ) ( Tx_Buff[ xIndex ] ); -// } -// #endif - -// if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE ) -// { -// /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */ -// pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL; -// } -// else -// { -// pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL ); -// } - -// /* Initialize the next descriptor with the Next Descriptor Polling Enable */ -// if( xIndex < ETH_TXBUFNB - 1 ) -// { -// /* Set next descriptor address register with next descriptor base address */ -// pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 ); -// } -// else -// { -// /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ -// pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab; -// } -// } - -// /* Set Transmit Descriptor List Address Register */ -// xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab; -//} -///*-----------------------------------------------------------*/ - -//static void prvDMARxDescListInit() -//{ -// ETH_DMADescTypeDef * pxDMADescriptor; -// BaseType_t xIndex; - -// /* -// * RX-descriptors. -// */ - -// /* Get the pointer on the first member of the descriptor list */ -// pxDMADescriptor = DMARxDscrTab; - -// /* Fill each DMA descriptor with the right values */ -// for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ ) -// { -// /* Set Buffer1 size and Second Address Chained bit */ -// pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | EMAC_DMA_BUFFER_SIZE; - -// #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) -// { -// /* Set Buffer1 address pointer */ -// NetworkBufferDescriptor_t * pxBuffer; - -// pxBuffer = pxGetNetworkBufferWithDescriptor( EMAC_DMA_BUFFER_SIZE, 100ul ); - -// /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB' -// * Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */ -// configASSERT( pxBuffer != NULL ); - -// if( pxBuffer != NULL ) -// { -// pxDMADescriptor->Buffer1Addr = ( uint32_t ) pxBuffer->pucEthernetBuffer; -// pxDMADescriptor->Status = ETH_DMARXDESC_OWN; -// } -// } -// #else /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ -// { -// /* Set Buffer1 address pointer */ -// pxDMADescriptor->Buffer1Addr = ( uint32_t ) ( Rx_Buff[ xIndex ] ); -// /* Set Own bit of the Rx descriptor Status */ -// pxDMADescriptor->Status = ETH_DMARXDESC_OWN; -// } -// #endif /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ - -// /* Initialize the next descriptor with the Next Descriptor Polling Enable */ -// if( xIndex < ETH_RXBUFNB - 1 ) -// { -// /* Set next descriptor address register with next descriptor base address */ -// pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 ); -// } -// else -// { -// /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ -// pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab; -// } -// } - -// /* Set Receive Descriptor List Address Register */ -// xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab; -//} -///*-----------------------------------------------------------*/ - -//#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) -// static void prvMACAddressConfig( ETH_HandleTypeDef * heth, -// uint32_t ulIndex, -// uint8_t * Addr ) -// { -// uint32_t ulTempReg; - -// ( void ) heth; - -// /* Calculate the selected MAC address high register. */ -// ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ]; - -// /* Load the selected MAC address high register. */ -// ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg; - -// /* Calculate the selected MAC address low register. */ -// ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ]; - -// /* Load the selected MAC address low register */ -// ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg; -// } -//#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) */ -///*-----------------------------------------------------------*/ - -//BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, -// BaseType_t bReleaseAfterSend ) -//{ -// BaseType_t xReturn = pdFAIL; -// uint32_t ulTransmitSize = 0; -// __IO ETH_DMADescTypeDef * pxDmaTxDesc; -///* Do not wait too long for a free TX DMA buffer. */ -// const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); - -// /* Open a do {} while ( 0 ) loop to be able to call break. */ -// do -// { -// #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) -// { -// ProtocolPacket_t * pxPacket; - -// /* If the peripheral must calculate the checksum, it wants -// * the protocol checksum to have a value of zero. */ -// pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer ); - -// if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) -// { -// pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t ) 0u; -// } -// } -// #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ - -// if( xPhyObject.ulLinkStatusMask != 0 ) -// { -// if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS ) -// { -// /* Time-out waiting for a free TX descriptor. */ -// break; -// } - -// /* This function does the actual transmission of the packet. The packet is -// * contained in 'pxDescriptor' that is passed to the function. */ -// pxDmaTxDesc = xETH.TxDesc; - -// /* Is this buffer available? */ -// configASSERT( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 ); - -// { -// /* Is this buffer available? */ -// /* Get bytes in current buffer. */ -// ulTransmitSize = pxDescriptor->xDataLength; - -// if( ulTransmitSize > EMAC_DMA_BUFFER_SIZE ) -// { -// ulTransmitSize = EMAC_DMA_BUFFER_SIZE; -// } - -// #if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) -// { -// /* Copy the bytes. */ -// memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize ); -// } -// #else -// { -// configASSERT( bReleaseAfterSend != 0 ); - -// /* Move the buffer. */ -// pxDmaTxDesc->Buffer1Addr = ( uint32_t ) pxDescriptor->pucEthernetBuffer; -// /* The Network Buffer has been passed to DMA, no need to release it. */ -// bReleaseAfterSend = pdFALSE_UNSIGNED; -// } -// #endif /* ipconfigZERO_COPY_TX_DRIVER */ - -// /* Ask to set the IPv4 checksum. -// * Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */ -// #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) -// { -// pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC; -// } -// #else -// { -// pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC ); -// pxDmaTxDesc->Status |= ETH_DMATXDESC_IC; -// } -// #endif - - -// /* Prepare transmit descriptors to give to DMA. */ - -// /* Set LAST and FIRST segment */ -// pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS; -// /* Set frame size */ -// pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 ); - -// #if ( NETWORK_BUFFERS_CACHED != 0 ) -// { -// BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE ); -// uint32_t * pulBuffer = ( uint32_t ) ( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE ); -// cache_clean_invalidate_by_addr( pulBuffer, xlength ); -// } -// #endif - -// /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ -// pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN; - -// /* Point to next descriptor */ -// xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr ); -// /* Ensure completion of memory access */ -// __DSB(); -// /* Resume DMA transmission*/ -// xETH.Instance->DMATPDR = 0; -// iptraceNETWORK_INTERFACE_TRANSMIT(); -// xReturn = pdPASS; -// } -// } -// else -// { -// /* The PHY has no Link Status, packet shall be dropped. */ -// } -// } while( 0 ); - -// /* The buffer has been sent so can be released. */ -// if( bReleaseAfterSend != pdFALSE ) -// { -// vReleaseNetworkBufferAndDescriptor( pxDescriptor ); -// } - -// return xReturn; -//} -///*-----------------------------------------------------------*/ - -//static BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ) -//{ -// const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; - -// switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) -// { -// case ipARP_FRAME_TYPE: -// /* Check it later. */ -// return pdTRUE; - -// case ipIPv4_FRAME_TYPE: -// /* Check it here. */ -// break; - -// default: -// /* Refuse the packet. */ -// return pdFALSE; -// } - -// #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 ) -// { -// const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); -// uint32_t ulDestinationIPAddress; - -// /* Ensure that the incoming packet is not fragmented (only outgoing packets -// * can be fragmented) as these are the only handled IP frames currently. */ -// if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) -// { -// return pdFALSE; -// } - -// /* HT: Might want to make the following configurable because -// * most IP messages have a standard length of 20 bytes */ - -// /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes -// * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */ -// if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) -// { -// return pdFALSE; -// } - -// ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; - -// /* Is the packet for this node? */ -// if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && -// /* Is it a broadcast address x.x.x.255 ? */ -// ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) && -// #if ( ipconfigUSE_LLMNR == 1 ) -// ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) && -// #endif -// ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) -// { -// FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) ); -// return pdFALSE; -// } - -// if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) -// { -// #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 ) || ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_DNS == 1 ) -// uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort ); -// uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ); -// #endif - -// if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE ) -// #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 -// ) -// { -// /* Drop this packet, not for this device. */ -// /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */ -// return pdFALSE; -// } -// } -// } -// #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ -// return pdTRUE; -//} -///*-----------------------------------------------------------*/ - -//static void prvPassEthMessages( NetworkBufferDescriptor_t * pxDescriptor ) -//{ -// IPStackEvent_t xRxEvent; - -// xRxEvent.eEventType = eNetworkRxEvent; -// xRxEvent.pvData = ( void * ) pxDescriptor; - -// if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS ) -// { -// /* The buffer could not be sent to the stack so must be released again. -// * This is a deferred handler task, not a real interrupt, so it is ok to -// * use the task level function here. */ -// #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) -// { -// do -// { -// NetworkBufferDescriptor_t * pxNext = pxDescriptor->pxNextBuffer; -// vReleaseNetworkBufferAndDescriptor( pxDescriptor ); -// pxDescriptor = pxNext; -// } while( pxDescriptor != NULL ); -// } -// #else -// { -// vReleaseNetworkBufferAndDescriptor( pxDescriptor ); -// } -// #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ -// iptraceETHERNET_RX_EVENT_LOST(); -// FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) ); -// } -// else -// { -// iptraceNETWORK_INTERFACE_RECEIVE(); -// } -//} - -//static BaseType_t prvNetworkInterfaceInput( void ) -//{ -// #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) -// NetworkBufferDescriptor_t * pxFirstDescriptor = NULL; -// NetworkBufferDescriptor_t * pxLastDescriptor = NULL; -// #endif -// BaseType_t xReceivedLength = 0; -// __IO ETH_DMADescTypeDef * pxDMARxDescriptor; -// const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS ); -// uint8_t * pucBuffer; - -// pxDMARxDescriptor = xETH.RxDesc; - -// while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u ) -// { -// NetworkBufferDescriptor_t * pxCurDescriptor; -// NetworkBufferDescriptor_t * pxNewDescriptor = NULL; -// BaseType_t xAccepted = pdTRUE; - -// /* Get the Frame Length of the received packet: subtract 4 bytes of the CRC */ -// xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4; - -// pucBuffer = ( uint8_t * ) pxDMARxDescriptor->Buffer1Addr; - -// /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */ -// /* Chained Mode */ -// /* Selects the next DMA Rx descriptor list for next buffer to read */ -// xETH.RxDesc = ( ETH_DMADescTypeDef * ) pxDMARxDescriptor->Buffer2NextDescAddr; - -// /* In order to make the code easier and faster, only packets in a single buffer -// * will be accepted. This can be done by making the buffers large enough to -// * hold a complete Ethernet packet, minus ipBUFFER_PADDING. -// * Therefore, two sanity checks: */ -// configASSERT( xReceivedLength <= EMAC_DMA_BUFFER_SIZE ); - -// if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT ) -// { -// /* Not an Ethernet frame-type or a checksum error. */ -// xAccepted = pdFALSE; -// } -// else -// { -// /* See if this packet must be handled. */ -// xAccepted = xMayAcceptPacket( pucBuffer ); -// } - -// if( xAccepted != pdFALSE ) -// { -// /* The packet will be accepted, but check first if a new Network Buffer can -// * be obtained. If not, the packet will still be dropped. */ -// pxNewDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DMA_BUFFER_SIZE, xDescriptorWaitTime ); - -// if( pxNewDescriptor == NULL ) -// { -// /* A new descriptor can not be allocated now. This packet will be dropped. */ -// xAccepted = pdFALSE; -// } -// } - -// #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) -// { -// /* Find out which Network Buffer was originally passed to the descriptor. */ -// pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer ); -// configASSERT( pxCurDescriptor != NULL ); -// } -// #else -// { -// /* In this mode, the two descriptors are the same. */ -// pxCurDescriptor = pxNewDescriptor; - -// if( pxNewDescriptor != NULL ) -// { -// /* The packet is accepted and a new Network Buffer was created, -// * copy data to the Network Buffer. */ -// memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength ); -// } -// } -// #endif /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ - -// if( xAccepted != pdFALSE ) -// { -// pxCurDescriptor->xDataLength = xReceivedLength; -// #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) -// { -// pxCurDescriptor->pxNextBuffer = NULL; - -// if( pxFirstDescriptor == NULL ) -// { -// /* Becomes the first message */ -// pxFirstDescriptor = pxCurDescriptor; -// } -// else if( pxLastDescriptor != NULL ) -// { -// /* Add to the tail */ -// pxLastDescriptor->pxNextBuffer = pxCurDescriptor; -// } - -// pxLastDescriptor = pxCurDescriptor; -// } -// #else /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ -// { -// prvPassEthMessages( pxCurDescriptor ); -// } -// #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ -// } - -// /* Release descriptors to DMA */ -// #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) -// { -// /* Set Buffer1 address pointer */ -// if( pxNewDescriptor != NULL ) -// { -// pxDMARxDescriptor->Buffer1Addr = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer; -// } -// else -// { -// /* The packet was dropped and the same Network -// * Buffer will be used to receive a new packet. */ -// } -// } -// #endif /* ipconfigZERO_COPY_RX_DRIVER */ - -// /* Set Buffer1 size and Second Address Chained bit */ -// pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | EMAC_DMA_BUFFER_SIZE; -// pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN; - -// /* Ensure completion of memory access */ -// __DSB(); - -// /* When Rx Buffer unavailable flag is set clear it and resume -// * reception. */ -// if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 ) -// { -// /* Clear RBUS ETHERNET DMA flag. */ -// xETH.Instance->DMASR = ETH_DMASR_RBUS; - -// /* Resume DMA reception. */ -// xETH.Instance->DMARPDR = 0; -// } - -// pxDMARxDescriptor = xETH.RxDesc; -// } - -// #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) -// { -// if( pxFirstDescriptor != NULL ) -// { -// prvPassEthMessages( pxFirstDescriptor ); -// } -// } -// #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ - -// return( xReceivedLength > 0 ); -//} -///*-----------------------------------------------------------*/ - - -//BaseType_t xSTM32_PhyRead( BaseType_t xAddress, -// BaseType_t xRegister, -// uint32_t * pulValue ) -//{ -// uint16_t usPrevAddress = xETH.Init.PhyAddress; -// BaseType_t xResult; -// HAL_StatusTypeDef xHALResult; - -// xETH.Init.PhyAddress = xAddress; -// xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t ) xRegister, pulValue ); -// xETH.Init.PhyAddress = usPrevAddress; - -// if( xHALResult == HAL_OK ) -// { -// xResult = 0; -// } -// else -// { -// xResult = -1; -// } - -// return xResult; -//} -///*-----------------------------------------------------------*/ - -//BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, -// BaseType_t xRegister, -// uint32_t ulValue ) -//{ -// uint16_t usPrevAddress = xETH.Init.PhyAddress; -// BaseType_t xResult; -// HAL_StatusTypeDef xHALResult; - -// xETH.Init.PhyAddress = xAddress; -// xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t ) xRegister, ulValue ); -// xETH.Init.PhyAddress = usPrevAddress; - -// if( xHALResult == HAL_OK ) -// { -// xResult = 0; -// } -// else -// { -// xResult = -1; -// } - -// return xResult; -//} -///*-----------------------------------------------------------*/ - -//void vMACBProbePhy( void ) -//{ -// vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite ); -// xPhyDiscover( &xPhyObject ); -// xPhyConfigure( &xPhyObject, &xPHYProperties ); -//} -///*-----------------------------------------------------------*/ - -//static void prvEthernetUpdateConfig( BaseType_t xForce ) -//{ -// FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n", -// xPhyObject.ulLinkStatusMask, -// ( int ) xForce ) ); - -// if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) ) -// { -// /* Restart the auto-negotiation. */ -// if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE ) -// { -// xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); - -// /* Configure the MAC with the Duplex Mode fixed by the -// * auto-negotiation process. */ -// if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) -// { -// xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; -// } -// else -// { -// xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX; -// } - -// /* Configure the MAC with the speed fixed by the -// * auto-negotiation process. */ -// if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) -// { -// xETH.Init.Speed = ETH_SPEED_10M; -// } -// else -// { -// xETH.Init.Speed = ETH_SPEED_100M; -// } -// } -// else /* AutoNegotiation Disable */ -// { -// /* Check parameters */ -// assert_param( IS_ETH_SPEED( xETH.Init.Speed ) ); -// assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) ); - -// if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX ) -// { -// xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF; -// } -// else -// { -// xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL; -// } - -// if( xETH.Init.Speed == ETH_SPEED_10M ) -// { -// xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10; -// } -// else -// { -// xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100; -// } - -// xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO; - -// /* Use predefined (fixed) configuration. */ -// xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); -// } - -// /* ETHERNET MAC Re-Configuration */ -// HAL_ETH_ConfigMAC( &xETH, ( ETH_MACInitTypeDef * ) NULL ); - -// /* Restart MAC interface */ -// HAL_ETH_Start( &xETH ); -// } -// else -// { -// /* Stop MAC interface */ -// HAL_ETH_Stop( &xETH ); -// } -//} -///*-----------------------------------------------------------*/ - -//BaseType_t xGetPhyLinkStatus( void ) -//{ -// BaseType_t xReturn; - -// if( xPhyObject.ulLinkStatusMask != 0 ) -// { -// xReturn = pdPASS; -// } -// else -// { -// xReturn = pdFAIL; -// } - -// return xReturn; -//} -///*-----------------------------------------------------------*/ - -///* Uncomment this in case BufferAllocation_1.c is used. */ - -//void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) -//{ -// static -// #if defined( STM32F7xx ) -// __attribute__( ( section( ".first_data" ) ) ) -// #endif -// uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__( ( aligned( 32 ) ) ); -// uint8_t * ucRAMBuffer = ucNetworkPackets; -// uint32_t ul; - -// for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) -// { -// pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; -// *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); -// ucRAMBuffer += ETH_MAX_PACKET_SIZE; -// } -//} -///*-----------------------------------------------------------*/ - -//static void prvEMACHandlerTask( void * pvParameters ) -//{ -// UBaseType_t uxCurrentCount; -// BaseType_t xResult; -// const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); -// uint32_t ulISREvents = 0U; - -// /* Remove compiler warnings about unused parameters. */ -// ( void ) pvParameters; - -// for( ; ; ) -// { -// xResult = 0; - -// #if ( ipconfigHAS_PRINTF != 0 ) -// { -// /* Call a function that monitors resources: the amount of free network -// * buffers and the amount of free space on the heap. See FreeRTOS_IP.c -// * for more detailed comments. */ -// vPrintResourceStats(); -// } -// #endif /* ( ipconfigHAS_PRINTF != 0 ) */ - -// if( xTXDescriptorSemaphore != NULL ) -// { -// static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1; - -// uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore ); - -// if( uxLowestSemCount > uxCurrentCount ) -// { -// uxLowestSemCount = uxCurrentCount; -// FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) ); -// } -// } - -// /* Wait for a new event or a time-out. */ -// xTaskNotifyWait( 0U, /* ulBitsToClearOnEntry */ -// EMAC_IF_ALL_EVENT, /* ulBitsToClearOnExit */ -// &( ulISREvents ), /* pulNotificationValue */ -// ulMaxBlockTime ); - -// if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) -// { -// xResult = prvNetworkInterfaceInput(); -// } - -// if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) -// { -// /* Code to release TX buffers in case zero-copy is used. */ -// /* Check if DMA packets have been delivered. */ -// vClearTXBuffers(); -// } - -// if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) -// { -// /* Future extension: logging about errors that occurred. */ -// } - -// if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) -// { -// /* Something has changed to a Link Status, need re-check. */ -// prvEthernetUpdateConfig( pdFALSE ); -// } -// } -//} -///*-----------------------------------------------------------*/ - -//void ETH_IRQHandler( void ) -//{ -// HAL_ETH_IRQHandler( &xETH ); -//} + + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxNetworkBuffer, + BaseType_t xReleaseAfterSend ) +{ + /* FIX ME. */ + return pdFALSE; +} + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + /* FIX ME. */ +} + +BaseType_t xGetPhyLinkStatus( void ) +{ + /* FIX ME. */ + return pdFALSE; +} + + + + +/* ST includes. */ +#if defined( GD32F10X_CL ) + #include "gd32f10x_enet.h" +#elif defined( STM32F7xx ) + #include "stm32f7xx_hal.h" + #define CACHE_LINE_SIZE 32u +#elif defined( STM32F4xx ) + #include "stm32f4xx_hal.h" +#elif defined( STM32F2xx ) + #include "stm32f2xx_hal.h" +#elif defined( STM32F1xx ) + #include "stm32f1xx_hal.h" +#elif !defined( _lint ) /* Lint does not like an #error */ + #error What part? +#endif /* if defined( GD32F10X_CL ) */ + + +/* Interrupt events to process. Currently only the Rx event is processed + * although code for other events is included to allow for possible future + * expansion. */ +#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 ) + +/* Calculate the maximum packet size that the DMA can receive. */ +#define EMAC_DMA_BUFFER_SIZE ( ( uint32_t ) ( ETH_MAX_PACKET_SIZE - ipBUFFER_PADDING ) ) + +#define ETH_DMA_ALL_INTS \ + ( ETH_DMA_IT_TST | ETH_DMA_IT_PMT | ETH_DMA_IT_MMC | ETH_DMA_IT_NIS | \ + ETH_DMA_IT_AIS | ETH_DMA_IT_ER | ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | \ + ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | ETH_DMA_IT_TU | \ + ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T ) + +#ifndef NETWORK_BUFFER_HEADER_SIZE + #define NETWORK_BUFFER_HEADER_SIZE ( ipBUFFER_PADDING ) +#endif + +#ifndef niEMAC_HANDLER_TASK_PRIORITY + #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1 +#endif + +#if ( ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) ) + #warning Consider enabling checksum offloading +#endif + +#ifndef niDESCRIPTOR_WAIT_TIME_MS + #define niDESCRIPTOR_WAIT_TIME_MS 250uL +#endif + +/* + * Most users will want a PHY that negotiates about + * the connection properties: speed, dmix and duplex. + * On some rare cases, you want to select what is being + * advertised, properties like MDIX and duplex. + */ + +#if !defined( ipconfigETHERNET_AN_ENABLE ) + /* Enable auto-negotiation */ + #define ipconfigETHERNET_AN_ENABLE 1 +#endif + +#if !defined( ipconfigETHERNET_AUTO_CROSS_ENABLE ) + #define ipconfigETHERNET_AUTO_CROSS_ENABLE 1 +#endif + +#if ( ipconfigETHERNET_AN_ENABLE == 0 ) + +/* + * The following three defines are only used in case there + * is no auto-negotiation. + */ + #if !defined( ipconfigETHERNET_CROSSED_LINK ) + #define ipconfigETHERNET_CROSSED_LINK 1 + #endif + + #if !defined( ipconfigETHERNET_USE_100MB ) + #define ipconfigETHERNET_USE_100MB 1 + #endif + + #if !defined( ipconfigETHERNET_USE_FULL_DUPLEX ) + #define ipconfigETHERNET_USE_FULL_DUPLEX 1 + #endif +#endif /* ipconfigETHERNET_AN_ENABLE == 0 */ + +/* Default the size of the stack used by the EMAC deferred handler task to twice + * the size of the stack used by the idle task - but allow this to be overridden in + * FreeRTOSConfig.h as configMINIMAL_STACK_SIZE is a user definable constant. */ +#ifndef configEMAC_TASK_STACK_SIZE + #define configEMAC_TASK_STACK_SIZE ( 2 * configMINIMAL_STACK_SIZE ) +#endif + +/* Two choices must be made: RMII versus MII, + * and the index of the PHY in use ( between 0 and 31 ). */ +#ifndef ipconfigUSE_RMII + #ifdef GD32F10X_CL + #define ipconfigUSE_RMII 1 + #warning Using RMII, make sure if this is correct + #else + #define ipconfigUSE_RMII 0 + #warning Using MII, make sure if this is correct + #endif /* GD32F10X_CL */ +#endif /* ipconfigUSE_RMII */ + +typedef enum +{ + eMACInit, /* Must initialise MAC. */ + eMACPass, /* Initialisation was successful. */ + eMACFailed, /* Initialisation failed. */ +} eMAC_INIT_STATUS_TYPE; + +static eMAC_INIT_STATUS_TYPE xMacInitStatus = eMACInit; + +/*-----------------------------------------------------------*/ + +/* + * A deferred interrupt handler task that processes + */ +static void prvEMACHandlerTask( void * pvParameters ); + +/* + * Force a negotiation with the Switch or Router and wait for LS. + */ +static void prvEthernetUpdateConfig( BaseType_t xForce ); + +/* + * See if there is a new packet and forward it to the IP-task. + */ +static BaseType_t prvNetworkInterfaceInput( void ); + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) + +/* + * For LLMNR, an extra MAC-address must be configured to + * be able to receive the multicast messages. + */ + static void prvMACAddressConfig( ETH_HandleTypeDef * heth, + uint32_t ulIndex, + uint8_t * Addr ); +#endif + +/* + * Check if a given packet should be accepted. + */ +static BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ); + +/* + * Initialise the TX descriptors. + */ +static void prvDMATxDescListInit( void ); + +/* + * Initialise the RX descriptors. + */ +static void prvDMARxDescListInit( void ); + +/* After packets have been sent, the network + * buffers will be released. */ +static void vClearTXBuffers( void ); + +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_LLMNR == 1 ) + static const uint8_t xLLMNR_MACAddress[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0xFC }; +#endif + +static EthernetPhy_t xPhyObject; + +/* Ethernet handle. */ +static ETH_HandleTypeDef xETH; + +/* xTXDescriptorSemaphore is a counting semaphore with + * a maximum count of ETH_TXBUFNB, which is the number of + * DMA TX descriptors. */ +static SemaphoreHandle_t xTXDescriptorSemaphore = NULL; + +/* + * Note: it is advised to define both + * + * #define ipconfigZERO_COPY_RX_DRIVER 1 + * #define ipconfigZERO_COPY_TX_DRIVER 1 + * + * The method using memcpy is slower and probably uses more RAM memory. + * The possibility is left in the code just for comparison. + * + * It is advised to define ETH_TXBUFNB at least 4. Note that no + * TX buffers are allocated in a zero-copy driver. + */ +/* MAC buffers: ---------------------------------------------------------*/ + +/* Put the DMA descriptors in '.first_data'. + * This is important for STM32F7, which has an L1 data cache. + * The first 64KB of the SRAM is not cached. + * See README.TXT in this folder. */ + +/* Ethernet Rx MA Descriptor */ +__attribute__( ( aligned( 32 ) ) ) +#if defined( STM32F7xx ) + __attribute__( ( section( ".first_data" ) ) ) +#endif +ETH_DMADescTypeDef DMARxDscrTab[ ETH_RXBUFNB ]; + +#if ( ipconfigZERO_COPY_RX_DRIVER == 0 ) + /* Ethernet Receive Buffer */ + __ALIGN_BEGIN uint8_t Rx_Buff[ ETH_RXBUFNB ][ ETH_RX_BUF_SIZE ] __ALIGN_END; +#endif + +/* Ethernet Tx DMA Descriptor */ +__attribute__( ( aligned( 32 ) ) ) +#if defined( STM32F7xx ) + __attribute__( ( section( ".first_data" ) ) ) +#endif +ETH_DMADescTypeDef DMATxDscrTab[ ETH_TXBUFNB ]; + +#if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) + /* Ethernet Transmit Buffer */ + __ALIGN_BEGIN uint8_t Tx_Buff[ ETH_TXBUFNB ][ ETH_TX_BUF_SIZE ] __ALIGN_END; +#endif + +/* DMATxDescToClear points to the next TX DMA descriptor + * that must be cleared by vClearTXBuffers(). */ +static __IO ETH_DMADescTypeDef * DMATxDescToClear; + +/* Holds the handle of the task used as a deferred interrupt processor. The + * handle is used so direct notifications can be sent to the task for all EMAC/DMA + * related interrupts. */ +static TaskHandle_t xEMACTaskHandle = NULL; + +/* For local use only: describe the PHY's properties: */ +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 ) */ + + #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 +}; + +/*-----------------------------------------------------------*/ + +void HAL_ETH_RxCpltCallback( ETH_HandleTypeDef * heth ) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + ( void ) heth; + + /* Pass an RX-event and wakeup the prvEMACHandlerTask. */ + if( xEMACTaskHandle != NULL ) + { + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_RX_EVENT, eSetBits, &( xHigherPriorityTaskWoken ) ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} +/*-----------------------------------------------------------*/ + +void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef * heth ) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + ( void ) heth; + + /* Pass a TX-event and wakeup the prvEMACHandlerTask. */ + if( xEMACTaskHandle != NULL ) + { + xTaskNotifyFromISR( xEMACTaskHandle, EMAC_IF_TX_EVENT, eSetBits, &( xHigherPriorityTaskWoken ) ); + portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); + } +} +/*-----------------------------------------------------------*/ + +static void vClearTXBuffers() +{ + __IO ETH_DMADescTypeDef * txLastDescriptor = xETH.TxDesc; + size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore ); + + #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) + NetworkBufferDescriptor_t * pxNetworkBuffer; + uint8_t * ucPayLoad; + #endif + + /* This function is called after a TX-completion interrupt. + * It will release each Network Buffer used in xNetworkInterfaceOutput(). + * 'uxCount' represents the number of descriptors given to DMA for transmission. + * After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */ + while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) ) + { + if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) ) + { + break; + } + + #if ( ipconfigZERO_COPY_TX_DRIVER != 0 ) + { + ucPayLoad = ( uint8_t * ) DMATxDescToClear->Buffer1Addr; + + if( ucPayLoad != NULL ) + { + pxNetworkBuffer = pxPacketBuffer_to_NetworkBuffer( ucPayLoad ); + + if( pxNetworkBuffer != NULL ) + { + vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ); + } + + DMATxDescToClear->Buffer1Addr = ( uint32_t ) 0u; + } + } + #endif /* ipconfigZERO_COPY_TX_DRIVER */ + + DMATxDescToClear = ( ETH_DMADescTypeDef * ) ( DMATxDescToClear->Buffer2NextDescAddr ); + + uxCount--; + /* Tell the counting semaphore that one more TX descriptor is available. */ + xSemaphoreGive( xTXDescriptorSemaphore ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceInitialise( void ) +{ + HAL_StatusTypeDef hal_eth_init_status; + BaseType_t xResult; + + #if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) + BaseType_t xMACEntry = ETH_MAC_ADDRESS1; /* ETH_MAC_ADDRESS0 reserved for the primary MAC-address. */ + #endif + + if( xMacInitStatus == eMACInit ) + { + xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB ); + + if( xTXDescriptorSemaphore == NULL ) + { + xMacInitStatus = eMACFailed; + } + else + { + /* Initialise ETH */ + + xETH.Instance = ETH; + xETH.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE; + xETH.Init.Speed = ETH_SPEED_100M; + xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + /* Value of PhyAddress doesn't matter, will be probed for. */ + xETH.Init.PhyAddress = 0; + + xETH.Init.MACAddr = ( uint8_t * ) FreeRTOS_GetMACAddress(); + xETH.Init.RxMode = ETH_RXINTERRUPT_MODE; + + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + { + /* using the ETH_CHECKSUM_BY_HARDWARE option: + * both the IP and the protocol checksums will be calculated + * by the peripheral. */ + xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE; + } + #else + { + xETH.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; + } + #endif + + #if ( ipconfigUSE_RMII != 0 ) + { + xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII; + } + #else + { + xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII; + } + #endif /* ipconfigUSE_RMII */ + + hal_eth_init_status = HAL_ETH_Init( &xETH ); + + /* Only for inspection by debugger. */ + ( void ) hal_eth_init_status; + + /* Set the TxDesc and RxDesc pointers. */ + xETH.TxDesc = DMATxDscrTab; + xETH.RxDesc = DMARxDscrTab; + + /* Make sure that all unused fields are cleared. */ + memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) ); + memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) ); + + /* Initialize Tx Descriptors list: Chain Mode */ + DMATxDescToClear = DMATxDscrTab; + + /* Initialise TX-descriptors. */ + prvDMATxDescListInit(); + + /* Initialise RX-descriptors. */ + prvDMARxDescListInit(); + + #if ( ipconfigUSE_MDNS == 1 ) + { + /* Program the MDNS address. */ + prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xMDNS_MACAddressIPv4 ); + xMACEntry += 8; + } + #endif + #if ( ipconfigUSE_LLMNR == 1 ) + { + /* Program the LLMNR address. */ + prvMACAddressConfig( &xETH, xMACEntry, ( uint8_t * ) xLLMNR_MACAddress ); + xMACEntry += 8; + } + #endif + + /* Force a negotiation with the Switch or Router and wait for LS. */ + prvEthernetUpdateConfig( pdTRUE ); + + /* The deferred interrupt handler task is created at the highest + * possible priority to ensure the interrupt handler can return directly + * to it. The task's handle is stored in xEMACTaskHandle so interrupts can + * notify the task when there is something to process. */ + if( xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle ) == pdPASS ) + { + /* The xTXDescriptorSemaphore and the task are created successfully. */ + xMacInitStatus = eMACPass; + } + else + { + xMacInitStatus = eMACFailed; + } + } + } /* if( xMacInitStatus == eMACInit ) */ + + if( xMacInitStatus != eMACPass ) + { + /* EMAC initialisation failed, return pdFAIL. */ + xResult = pdFAIL; + } + else + { + if( xPhyObject.ulLinkStatusMask != 0U ) + { + xETH.Instance->DMAIER |= ETH_DMA_ALL_INTS; + xResult = pdPASS; + FreeRTOS_printf( ( "Link Status is high\n" ) ); + } + else + { + /* For now pdFAIL will be returned. But prvEMACHandlerTask() is running + * and it will keep on checking the PHY and set 'ulLinkStatusMask' when necessary. */ + xResult = pdFAIL; + } + } + + /* When returning non-zero, the stack will become active and + * start DHCP (in configured) */ + return xResult; +} +/*-----------------------------------------------------------*/ + +static void prvDMATxDescListInit() +{ + ETH_DMADescTypeDef * pxDMADescriptor; + BaseType_t xIndex; + + /* Get the pointer on the first member of the descriptor list */ + pxDMADescriptor = DMATxDscrTab; + + /* Fill each DMA descriptor with the right values */ + for( xIndex = 0; xIndex < ETH_TXBUFNB; xIndex++, pxDMADescriptor++ ) + { + /* Set Second Address Chained bit */ + pxDMADescriptor->Status = ETH_DMATXDESC_TCH; + + #if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) + { + /* Set Buffer1 address pointer */ + pxDMADescriptor->Buffer1Addr = ( uint32_t ) ( Tx_Buff[ xIndex ] ); + } + #endif + + if( xETH.Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE ) + { + /* Set the DMA Tx descriptors checksum insertion for TCP, UDP, and ICMP */ + pxDMADescriptor->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL; + } + else + { + pxDMADescriptor->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL ); + } + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if( xIndex < ETH_TXBUFNB - 1 ) + { + /* Set next descriptor address register with next descriptor base address */ + pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 ); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMATxDscrTab; + } + } + + /* Set Transmit Descriptor List Address Register */ + xETH.Instance->DMATDLAR = ( uint32_t ) DMATxDscrTab; +} +/*-----------------------------------------------------------*/ + +static void prvDMARxDescListInit() +{ + ETH_DMADescTypeDef * pxDMADescriptor; + BaseType_t xIndex; + + /* + * RX-descriptors. + */ + + /* Get the pointer on the first member of the descriptor list */ + pxDMADescriptor = DMARxDscrTab; + + /* Fill each DMA descriptor with the right values */ + for( xIndex = 0; xIndex < ETH_RXBUFNB; xIndex++, pxDMADescriptor++ ) + { + /* Set Buffer1 size and Second Address Chained bit */ + pxDMADescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | EMAC_DMA_BUFFER_SIZE; + + #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) + { + /* Set Buffer1 address pointer */ + NetworkBufferDescriptor_t * pxBuffer; + + pxBuffer = pxGetNetworkBufferWithDescriptor( EMAC_DMA_BUFFER_SIZE, 100ul ); + + /* If the assert below fails, make sure that there are at least 'ETH_RXBUFNB' + * Network Buffers available during start-up ( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ) */ + configASSERT( pxBuffer != NULL ); + + if( pxBuffer != NULL ) + { + pxDMADescriptor->Buffer1Addr = ( uint32_t ) pxBuffer->pucEthernetBuffer; + pxDMADescriptor->Status = ETH_DMARXDESC_OWN; + } + } + #else /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ + { + /* Set Buffer1 address pointer */ + pxDMADescriptor->Buffer1Addr = ( uint32_t ) ( Rx_Buff[ xIndex ] ); + /* Set Own bit of the Rx descriptor Status */ + pxDMADescriptor->Status = ETH_DMARXDESC_OWN; + } + #endif /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ + + /* Initialize the next descriptor with the Next Descriptor Polling Enable */ + if( xIndex < ETH_RXBUFNB - 1 ) + { + /* Set next descriptor address register with next descriptor base address */ + pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) ( pxDMADescriptor + 1 ); + } + else + { + /* For last descriptor, set next descriptor address register equal to the first descriptor base address */ + pxDMADescriptor->Buffer2NextDescAddr = ( uint32_t ) DMARxDscrTab; + } + } + + /* Set Receive Descriptor List Address Register */ + xETH.Instance->DMARDLAR = ( uint32_t ) DMARxDscrTab; +} +/*-----------------------------------------------------------*/ + +#if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) + static void prvMACAddressConfig( ETH_HandleTypeDef * heth, + uint32_t ulIndex, + uint8_t * Addr ) + { + uint32_t ulTempReg; + + ( void ) heth; + + /* Calculate the selected MAC address high register. */ + ulTempReg = 0x80000000ul | ( ( uint32_t ) Addr[ 5 ] << 8 ) | ( uint32_t ) Addr[ 4 ]; + + /* Load the selected MAC address high register. */ + ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_HBASE + ulIndex ) ) ) = ulTempReg; + + /* Calculate the selected MAC address low register. */ + ulTempReg = ( ( uint32_t ) Addr[ 3 ] << 24 ) | ( ( uint32_t ) Addr[ 2 ] << 16 ) | ( ( uint32_t ) Addr[ 1 ] << 8 ) | Addr[ 0 ]; + + /* Load the selected MAC address low register */ + ( *( __IO uint32_t * ) ( ( uint32_t ) ( ETH_MAC_ADDR_LBASE + ulIndex ) ) ) = ulTempReg; + } +#endif /* if ( ipconfigUSE_LLMNR != 0 ) || ( ipconfigUSE_MDNS != 0 ) */ +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkInterfaceOutput( NetworkBufferDescriptor_t * const pxDescriptor, + BaseType_t bReleaseAfterSend ) +{ + BaseType_t xReturn = pdFAIL; + uint32_t ulTransmitSize = 0; + __IO ETH_DMADescTypeDef * pxDmaTxDesc; +/* Do not wait too long for a free TX DMA buffer. */ + const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u ); + + /* Open a do {} while ( 0 ) loop to be able to call break. */ + do + { + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + { + ProtocolPacket_t * pxPacket; + + /* If the peripheral must calculate the checksum, it wants + * the protocol checksum to have a value of zero. */ + pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer ); + + if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) + { + pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t ) 0u; + } + } + #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */ + + if( xPhyObject.ulLinkStatusMask != 0 ) + { + if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS ) + { + /* Time-out waiting for a free TX descriptor. */ + break; + } + + /* This function does the actual transmission of the packet. The packet is + * contained in 'pxDescriptor' that is passed to the function. */ + pxDmaTxDesc = xETH.TxDesc; + + /* Is this buffer available? */ + configASSERT( ( pxDmaTxDesc->Status & ETH_DMATXDESC_OWN ) == 0 ); + + { + /* Is this buffer available? */ + /* Get bytes in current buffer. */ + ulTransmitSize = pxDescriptor->xDataLength; + + if( ulTransmitSize > EMAC_DMA_BUFFER_SIZE ) + { + ulTransmitSize = EMAC_DMA_BUFFER_SIZE; + } + + #if ( ipconfigZERO_COPY_TX_DRIVER == 0 ) + { + /* Copy the bytes. */ + memcpy( ( void * ) pxDmaTxDesc->Buffer1Addr, pxDescriptor->pucEthernetBuffer, ulTransmitSize ); + } + #else + { + configASSERT( bReleaseAfterSend != 0 ); + + /* Move the buffer. */ + pxDmaTxDesc->Buffer1Addr = ( uint32_t ) pxDescriptor->pucEthernetBuffer; + /* The Network Buffer has been passed to DMA, no need to release it. */ + bReleaseAfterSend = pdFALSE_UNSIGNED; + } + #endif /* ipconfigZERO_COPY_TX_DRIVER */ + + /* Ask to set the IPv4 checksum. + * Also need an Interrupt on Completion so that 'vClearTXBuffers()' will be called.. */ + #if ( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) + { + pxDmaTxDesc->Status |= ETH_DMATXDESC_CIC_TCPUDPICMP_FULL | ETH_DMATXDESC_IC; + } + #else + { + pxDmaTxDesc->Status &= ~( ( uint32_t ) ETH_DMATXDESC_CIC ); + pxDmaTxDesc->Status |= ETH_DMATXDESC_IC; + } + #endif + + + /* Prepare transmit descriptors to give to DMA. */ + + /* Set LAST and FIRST segment */ + pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS; + /* Set frame size */ + pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 ); + + #if ( NETWORK_BUFFERS_CACHED != 0 ) + { + BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE ); + uint32_t * pulBuffer = ( uint32_t ) ( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE ); + cache_clean_invalidate_by_addr( pulBuffer, xlength ); + } + #endif + + /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */ + pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN; + + /* Point to next descriptor */ + xETH.TxDesc = ( ETH_DMADescTypeDef * ) ( xETH.TxDesc->Buffer2NextDescAddr ); + /* Ensure completion of memory access */ + __DSB(); + /* Resume DMA transmission*/ + xETH.Instance->DMATPDR = 0; + iptraceNETWORK_INTERFACE_TRANSMIT(); + xReturn = pdPASS; + } + } + else + { + /* The PHY has no Link Status, packet shall be dropped. */ + } + } while( 0 ); + + /* The buffer has been sent so can be released. */ + if( bReleaseAfterSend != pdFALSE ) + { + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static BaseType_t xMayAcceptPacket( uint8_t * pucEthernetBuffer ) +{ + const ProtocolPacket_t * pxProtPacket = ( const ProtocolPacket_t * ) pucEthernetBuffer; + + switch( pxProtPacket->xTCPPacket.xEthernetHeader.usFrameType ) + { + case ipARP_FRAME_TYPE: + /* Check it later. */ + return pdTRUE; + + case ipIPv4_FRAME_TYPE: + /* Check it here. */ + break; + + default: + /* Refuse the packet. */ + return pdFALSE; + } + + #if ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 1 ) + { + const IPHeader_t * pxIPHeader = &( pxProtPacket->xTCPPacket.xIPHeader ); + uint32_t ulDestinationIPAddress; + + /* Ensure that the incoming packet is not fragmented (only outgoing packets + * can be fragmented) as these are the only handled IP frames currently. */ + if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U ) + { + return pdFALSE; + } + + /* HT: Might want to make the following configurable because + * most IP messages have a standard length of 20 bytes */ + + /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes + * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */ + if( ( pxIPHeader->ucVersionHeaderLength < 0x45 ) || ( pxIPHeader->ucVersionHeaderLength > 0x4F ) ) + { + return pdFALSE; + } + + ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress; + + /* Is the packet for this node? */ + if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) && + /* Is it a broadcast address x.x.x.255 ? */ + ( ( FreeRTOS_ntohl( ulDestinationIPAddress ) & 0xff ) != 0xff ) && + #if ( ipconfigUSE_LLMNR == 1 ) + ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) && + #endif + ( *ipLOCAL_IP_ADDRESS_POINTER != 0 ) ) + { + FreeRTOS_printf( ( "Drop IP %lxip\n", FreeRTOS_ntohl( ulDestinationIPAddress ) ) ); + return pdFALSE; + } + + if( pxIPHeader->ucProtocol == ipPROTOCOL_UDP ) + { + #if ( ipconfigUSE_LLMNR == 1 ) || ( ipconfigUSE_MDNS == 1 ) || ( ipconfigUSE_NBNS == 1 ) || ( ipconfigUSE_DNS == 1 ) + uint16_t usSourcePort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usSourcePort ); + uint16_t usDestinationPort = FreeRTOS_ntohs( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ); + #endif + + if( ( xPortHasUDPSocket( pxProtPacket->xUDPPacket.xUDPHeader.usDestinationPort ) == pdFALSE ) + #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 + ) + { + /* Drop this packet, not for this device. */ + /* FreeRTOS_printf( ( "Drop: UDP port %d -> %d\n", usSourcePort, usDestinationPort ) ); */ + return pdFALSE; + } + } + } + #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */ + return pdTRUE; +} +/*-----------------------------------------------------------*/ + +static void prvPassEthMessages( NetworkBufferDescriptor_t * pxDescriptor ) +{ + IPStackEvent_t xRxEvent; + + xRxEvent.eEventType = eNetworkRxEvent; + xRxEvent.pvData = ( void * ) pxDescriptor; + + if( xSendEventStructToIPTask( &xRxEvent, ( TickType_t ) 1000 ) != pdPASS ) + { + /* The buffer could not be sent to the stack so must be released again. + * This is a deferred handler task, not a real interrupt, so it is ok to + * use the task level function here. */ + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + do + { + NetworkBufferDescriptor_t * pxNext = pxDescriptor->pxNextBuffer; + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + pxDescriptor = pxNext; + } while( pxDescriptor != NULL ); + } + #else + { + vReleaseNetworkBufferAndDescriptor( pxDescriptor ); + } + #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + iptraceETHERNET_RX_EVENT_LOST(); + FreeRTOS_printf( ( "prvPassEthMessages: Can not queue return packet!\n" ) ); + } + else + { + iptraceNETWORK_INTERFACE_RECEIVE(); + } +} + +static BaseType_t prvNetworkInterfaceInput( void ) +{ + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + NetworkBufferDescriptor_t * pxFirstDescriptor = NULL; + NetworkBufferDescriptor_t * pxLastDescriptor = NULL; + #endif + BaseType_t xReceivedLength = 0; + __IO ETH_DMADescTypeDef * pxDMARxDescriptor; + const TickType_t xDescriptorWaitTime = pdMS_TO_TICKS( niDESCRIPTOR_WAIT_TIME_MS ); + uint8_t * pucBuffer; + + pxDMARxDescriptor = xETH.RxDesc; + + while( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_OWN ) == 0u ) + { + NetworkBufferDescriptor_t * pxCurDescriptor; + NetworkBufferDescriptor_t * pxNewDescriptor = NULL; + BaseType_t xAccepted = pdTRUE; + + /* Get the Frame Length of the received packet: subtract 4 bytes of the CRC */ + xReceivedLength = ( ( pxDMARxDescriptor->Status & ETH_DMARXDESC_FL ) >> ETH_DMARXDESC_FRAMELENGTHSHIFT ) - 4; + + pucBuffer = ( uint8_t * ) pxDMARxDescriptor->Buffer1Addr; + + /* Update the ETHERNET DMA global Rx descriptor with next Rx descriptor */ + /* Chained Mode */ + /* Selects the next DMA Rx descriptor list for next buffer to read */ + xETH.RxDesc = ( ETH_DMADescTypeDef * ) pxDMARxDescriptor->Buffer2NextDescAddr; + + /* In order to make the code easier and faster, only packets in a single buffer + * will be accepted. This can be done by making the buffers large enough to + * hold a complete Ethernet packet, minus ipBUFFER_PADDING. + * Therefore, two sanity checks: */ + configASSERT( xReceivedLength <= EMAC_DMA_BUFFER_SIZE ); + + if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT ) + { + /* Not an Ethernet frame-type or a checksum error. */ + xAccepted = pdFALSE; + } + else + { + /* See if this packet must be handled. */ + xAccepted = xMayAcceptPacket( pucBuffer ); + } + + if( xAccepted != pdFALSE ) + { + /* The packet will be accepted, but check first if a new Network Buffer can + * be obtained. If not, the packet will still be dropped. */ + pxNewDescriptor = pxGetNetworkBufferWithDescriptor( EMAC_DMA_BUFFER_SIZE, xDescriptorWaitTime ); + + if( pxNewDescriptor == NULL ) + { + /* A new descriptor can not be allocated now. This packet will be dropped. */ + xAccepted = pdFALSE; + } + } + + #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) + { + /* Find out which Network Buffer was originally passed to the descriptor. */ + pxCurDescriptor = pxPacketBuffer_to_NetworkBuffer( pucBuffer ); + configASSERT( pxCurDescriptor != NULL ); + } + #else + { + /* In this mode, the two descriptors are the same. */ + pxCurDescriptor = pxNewDescriptor; + + if( pxNewDescriptor != NULL ) + { + /* The packet is accepted and a new Network Buffer was created, + * copy data to the Network Buffer. */ + memcpy( pxNewDescriptor->pucEthernetBuffer, pucBuffer, xReceivedLength ); + } + } + #endif /* if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) */ + + if( xAccepted != pdFALSE ) + { + pxCurDescriptor->xDataLength = xReceivedLength; + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + pxCurDescriptor->pxNextBuffer = NULL; + + if( pxFirstDescriptor == NULL ) + { + /* Becomes the first message */ + pxFirstDescriptor = pxCurDescriptor; + } + else if( pxLastDescriptor != NULL ) + { + /* Add to the tail */ + pxLastDescriptor->pxNextBuffer = pxCurDescriptor; + } + + pxLastDescriptor = pxCurDescriptor; + } + #else /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ + { + prvPassEthMessages( pxCurDescriptor ); + } + #endif /* if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) */ + } + + /* Release descriptors to DMA */ + #if ( ipconfigZERO_COPY_RX_DRIVER != 0 ) + { + /* Set Buffer1 address pointer */ + if( pxNewDescriptor != NULL ) + { + pxDMARxDescriptor->Buffer1Addr = ( uint32_t ) pxNewDescriptor->pucEthernetBuffer; + } + else + { + /* The packet was dropped and the same Network + * Buffer will be used to receive a new packet. */ + } + } + #endif /* ipconfigZERO_COPY_RX_DRIVER */ + + /* Set Buffer1 size and Second Address Chained bit */ + pxDMARxDescriptor->ControlBufferSize = ETH_DMARXDESC_RCH | EMAC_DMA_BUFFER_SIZE; + pxDMARxDescriptor->Status = ETH_DMARXDESC_OWN; + + /* Ensure completion of memory access */ + __DSB(); + + /* When Rx Buffer unavailable flag is set clear it and resume + * reception. */ + if( ( xETH.Instance->DMASR & ETH_DMASR_RBUS ) != 0 ) + { + /* Clear RBUS ETHERNET DMA flag. */ + xETH.Instance->DMASR = ETH_DMASR_RBUS; + + /* Resume DMA reception. */ + xETH.Instance->DMARPDR = 0; + } + + pxDMARxDescriptor = xETH.RxDesc; + } + + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + if( pxFirstDescriptor != NULL ) + { + prvPassEthMessages( pxFirstDescriptor ); + } + } + #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + + return( xReceivedLength > 0 ); +} +/*-----------------------------------------------------------*/ + + +BaseType_t xSTM32_PhyRead( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t * pulValue ) +{ + uint16_t usPrevAddress = xETH.Init.PhyAddress; + BaseType_t xResult; + HAL_StatusTypeDef xHALResult; + + xETH.Init.PhyAddress = xAddress; + xHALResult = HAL_ETH_ReadPHYRegister( &xETH, ( uint16_t ) xRegister, pulValue ); + xETH.Init.PhyAddress = usPrevAddress; + + if( xHALResult == HAL_OK ) + { + xResult = 0; + } + else + { + xResult = -1; + } + + return xResult; +} +/*-----------------------------------------------------------*/ + +BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, + BaseType_t xRegister, + uint32_t ulValue ) +{ + uint16_t usPrevAddress = xETH.Init.PhyAddress; + BaseType_t xResult; + HAL_StatusTypeDef xHALResult; + + xETH.Init.PhyAddress = xAddress; + xHALResult = HAL_ETH_WritePHYRegister( &xETH, ( uint16_t ) xRegister, ulValue ); + xETH.Init.PhyAddress = usPrevAddress; + + if( xHALResult == HAL_OK ) + { + xResult = 0; + } + else + { + xResult = -1; + } + + return xResult; +} +/*-----------------------------------------------------------*/ + +void vMACBProbePhy( void ) +{ + vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite ); + xPhyDiscover( &xPhyObject ); + xPhyConfigure( &xPhyObject, &xPHYProperties ); +} +/*-----------------------------------------------------------*/ + +static void prvEthernetUpdateConfig( BaseType_t xForce ) +{ + FreeRTOS_printf( ( "prvEthernetUpdateConfig: LS mask %02lX Force %d\n", + xPhyObject.ulLinkStatusMask, + ( int ) xForce ) ); + + if( ( xForce != pdFALSE ) || ( xPhyObject.ulLinkStatusMask != 0 ) ) + { + /* Restart the auto-negotiation. */ + if( xETH.Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE ) + { + xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + + /* Configure the MAC with the Duplex Mode fixed by the + * auto-negotiation process. */ + if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL ) + { + xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX; + } + else + { + xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX; + } + + /* Configure the MAC with the speed fixed by the + * auto-negotiation process. */ + if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 ) + { + xETH.Init.Speed = ETH_SPEED_10M; + } + else + { + xETH.Init.Speed = ETH_SPEED_100M; + } + } + else /* AutoNegotiation Disable */ + { + /* Check parameters */ + assert_param( IS_ETH_SPEED( xETH.Init.Speed ) ); + assert_param( IS_ETH_DUPLEX_MODE( xETH.Init.DuplexMode ) ); + + if( xETH.Init.DuplexMode == ETH_MODE_FULLDUPLEX ) + { + xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_HALF; + } + else + { + xPhyObject.xPhyPreferences.ucDuplex = PHY_DUPLEX_FULL; + } + + if( xETH.Init.Speed == ETH_SPEED_10M ) + { + xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_10; + } + else + { + xPhyObject.xPhyPreferences.ucSpeed = PHY_SPEED_100; + } + + xPhyObject.xPhyPreferences.ucMDI_X = PHY_MDIX_AUTO; + + /* Use predefined (fixed) configuration. */ + xPhyFixedValue( &xPhyObject, xPhyGetMask( &xPhyObject ) ); + } + + /* ETHERNET MAC Re-Configuration */ + HAL_ETH_ConfigMAC( &xETH, ( ETH_MACInitTypeDef * ) NULL ); + + /* Restart MAC interface */ + HAL_ETH_Start( &xETH ); + } + else + { + /* Stop MAC interface */ + HAL_ETH_Stop( &xETH ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xGetPhyLinkStatus( void ) +{ + BaseType_t xReturn; + + if( xPhyObject.ulLinkStatusMask != 0 ) + { + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +/* Uncomment this in case BufferAllocation_1.c is used. */ + +void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] ) +{ + static + #if defined( STM32F7xx ) + __attribute__( ( section( ".first_data" ) ) ) + #endif + uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * ETH_MAX_PACKET_SIZE ] __attribute__( ( aligned( 32 ) ) ); + uint8_t * ucRAMBuffer = ucNetworkPackets; + uint32_t ul; + + for( ul = 0; ul < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; ul++ ) + { + pxNetworkBuffers[ ul ].pucEthernetBuffer = ucRAMBuffer + ipBUFFER_PADDING; + *( ( unsigned * ) ucRAMBuffer ) = ( unsigned ) ( &( pxNetworkBuffers[ ul ] ) ); + ucRAMBuffer += ETH_MAX_PACKET_SIZE; + } +} +/*-----------------------------------------------------------*/ + +static void prvEMACHandlerTask( void * pvParameters ) +{ + UBaseType_t uxCurrentCount; + BaseType_t xResult; + const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( 100UL ); + uint32_t ulISREvents = 0U; + + /* Remove compiler warnings about unused parameters. */ + ( void ) pvParameters; + + for( ; ; ) + { + xResult = 0; + + #if ( ipconfigHAS_PRINTF != 0 ) + { + /* Call a function that monitors resources: the amount of free network + * buffers and the amount of free space on the heap. See FreeRTOS_IP.c + * for more detailed comments. */ + vPrintResourceStats(); + } + #endif /* ( ipconfigHAS_PRINTF != 0 ) */ + + if( xTXDescriptorSemaphore != NULL ) + { + static UBaseType_t uxLowestSemCount = ( UBaseType_t ) ETH_TXBUFNB - 1; + + uxCurrentCount = uxSemaphoreGetCount( xTXDescriptorSemaphore ); + + if( uxLowestSemCount > uxCurrentCount ) + { + uxLowestSemCount = uxCurrentCount; + FreeRTOS_printf( ( "TX DMA buffers: lowest %lu\n", uxLowestSemCount ) ); + } + } + + /* Wait for a new event or a time-out. */ + xTaskNotifyWait( 0U, /* ulBitsToClearOnEntry */ + EMAC_IF_ALL_EVENT, /* ulBitsToClearOnExit */ + &( ulISREvents ), /* pulNotificationValue */ + ulMaxBlockTime ); + + if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) + { + xResult = prvNetworkInterfaceInput(); + } + + if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) + { + /* Code to release TX buffers in case zero-copy is used. */ + /* Check if DMA packets have been delivered. */ + vClearTXBuffers(); + } + + if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) + { + /* Future extension: logging about errors that occurred. */ + } + + if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 ) + { + /* Something has changed to a Link Status, need re-check. */ + prvEthernetUpdateConfig( pdFALSE ); + } + } +} +/*-----------------------------------------------------------*/ + +void ETH_IRQHandler( void ) +{ + HAL_ETH_IRQHandler( &xETH ); +} /* * Some constants, hardware definitions and comments taken from ST's HAL driver * library, COPYRIGHT(c) 2015 STMicroelectronics. */ - +#endif /*STM32_PORT*/ diff --git a/RTE/RTOS/FreeRTOSConfig.h b/RTE/RTOS/FreeRTOSConfig.h index 5f073fc..25a3320 100644 --- a/RTE/RTOS/FreeRTOSConfig.h +++ b/RTE/RTOS/FreeRTOSConfig.h @@ -64,7 +64,7 @@ extern uint32_t SystemCoreClock; #define configUSE_16_BIT_TICKS 0 /* Software timer definitions. */ -#define configUSE_TIMERS 0 +#define configUSE_TIMERS 1 #define configTIMER_TASK_PRIORITY 2 #define configTIMER_QUEUE_LENGTH 5 #define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2) diff --git a/RTE/_Target_1/RTE_Components.h b/RTE/_Target_1/RTE_Components.h index 92c52af..dfb9180 100644 --- a/RTE/_Target_1/RTE_Components.h +++ b/RTE/_Target_1/RTE_Components.h @@ -24,6 +24,8 @@ #define RTE_RTOS_FreeRTOS_EVENTGROUPS /* RTOS FreeRTOS Event Groups */ /* ARM.FreeRTOS::RTOS:Heap:Heap_4:10.5.1 */ #define RTE_RTOS_FreeRTOS_HEAP_4 /* RTOS FreeRTOS Heap 4 */ +/* ARM.FreeRTOS::RTOS:Timers:10.5.1 */ +#define RTE_RTOS_FreeRTOS_TIMERS /* RTOS FreeRTOS Timers */ /* GigaDevice::Device:GD32F10x_StdPeripherals:BKP:2.0.2 */ #define RTE_DEVICE_STDPERIPHERALS_BKP /* GigaDevice::Device:GD32F10x_StdPeripherals:DMA:2.0.2 */ diff --git a/Test_project_for_GD32107C-EVAL.uvoptx b/Test_project_for_GD32107C-EVAL.uvoptx index 0eebea6..9ff495c 100644 --- a/Test_project_for_GD32107C-EVAL.uvoptx +++ b/Test_project_for_GD32107C-EVAL.uvoptx @@ -153,147 +153,34 @@ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0GD32F10x_CL -FS08000000 -FL040000 -FP0($$Device:GD32F107VC$Flash\GD32F10x_CL.FLM)) - - - 0 - 0 - 752 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - .\FreeRTOS\source\FreeRTOS_TCP_IP.c - - -
- - 1 - 0 - 760 - 1 -
0
- 0 - 0 - 0 - 0 - 0 - 0 - .\FreeRTOS\source\FreeRTOS_TCP_IP.c - - -
-
+ 0 1 - tickCounter + pxDMARxDescriptor 1 1 - xBoundTCPSocketsList + dma_current_rxdesc 2 1 - mac + pxDescriptor 3 1 - PHY - - - 4 - 1 - frame - - - 5 - 1 - dma_current_txdesc - - - 6 - 1 - xDHCPSocket - - - 7 - 1 - pucRxBuffer - - - 8 - 1 - EP_DHCPData - - - 9 - 1 - EP_IPv4_SETTINGS - - - 10 - 1 - xDHCPData - - - 11 - 1 - xNetworkAddressing - - - 12 - 1 - eLeasedAddress - - - 13 - 1 - pxSocket - - - 14 - 1 - prvServerConnectionInstance_Handle - - - 15 - 1 - pvBuffer - - - 16 - 1 - pxCurrentTCB - - - 17 - 1 - receiveBufferDescriptor - - - 18 - 1 - xNetworkEventQueue - - - 19 - 1 - FreeHeapSize + pucTemp 1 0 - frame + \\Test_project_for_GD32107C_EVAL\FreeRTOS/source/portable/NetworkInterface/board_family/NetworkInterface.c\receiveHandlerTask\pxDescriptor->pucEthernetBuffer 0 @@ -314,7 +201,7 @@ - C:\Users\User\AppData\Local\Arm\Packs\ARM\CMSIS-FreeRTOS\10.5.1\CMSIS\RTOS2\FreeRTOS\FreeRTOS.scvd + E:\Arm\Packs\ARM\CMSIS-FreeRTOS\10.5.1\CMSIS\RTOS2\FreeRTOS\FreeRTOS.scvd ARM.CMSIS-FreeRTOS.10.5.1 1 @@ -326,7 +213,7 @@ 1 1 0 - 1 + 0 0 0 1 diff --git a/Test_project_for_GD32107C-EVAL.uvprojx b/Test_project_for_GD32107C-EVAL.uvprojx index a8b77ec..71f7634 100644 --- a/Test_project_for_GD32107C-EVAL.uvprojx +++ b/Test_project_for_GD32107C-EVAL.uvprojx @@ -338,7 +338,7 @@ 0 0 - -D DEBUG -Wno-pragma-pack -Wno-macro-redefined + -D DEBUG -Wno-pragma-pack -Wno-macro-redefined -D CENTRALISED_DEFERRED_IRQ_HADLING .\FreeRTOS\source\portable\NetworkInterface\include;.\FreeRTOS\source\include;.\FreeRTOS\source\portable\Compiler\Keil;.\DemoTasks\include;..\GigaDevice_test;.\include;.\PHY @@ -795,6 +795,12 @@ + + + + + + diff --git a/main.c b/main.c index 08cd701..3404684 100644 --- a/main.c +++ b/main.c @@ -277,7 +277,7 @@ static void vInitMCU(void) /* Enable Ethernet MAC */ enet_descriptors_chain_init(ENET_DMA_TX); - enet_descriptors_chain_init(ENET_DMA_RX); //enet_desc_receive_complete_bit_enable(dma_current_rxdesc); + enet_descriptors_chain_init(ENET_DMA_RX); enet_enable(); //nvic_irq_enable(ENET_IRQn, ipconfigMAC_INTERRUPT_PRIORITY, 0xFF); __disable_irq();