mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K64F/drivers/fsl_enet.c@169:e3b6fe271b81, 2017-07-19 (annotated)
- Committer:
- Kojto
- Date:
- Wed Jul 19 17:31:21 2017 +0100
- Revision:
- 169:e3b6fe271b81
- Parent:
- 156:95d6b41a828b
This updates the lib to the mbed lib v 147
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
<> | 154:37f96f9d4de2 | 1 | /* |
<> | 154:37f96f9d4de2 | 2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. |
<> | 154:37f96f9d4de2 | 3 | * All rights reserved. |
<> | 154:37f96f9d4de2 | 4 | * |
<> | 154:37f96f9d4de2 | 5 | * Redistribution and use in source and binary forms, with or without modification, |
<> | 154:37f96f9d4de2 | 6 | * are permitted provided that the following conditions are met: |
<> | 154:37f96f9d4de2 | 7 | * |
<> | 154:37f96f9d4de2 | 8 | * o Redistributions of source code must retain the above copyright notice, this list |
<> | 154:37f96f9d4de2 | 9 | * of conditions and the following disclaimer. |
<> | 154:37f96f9d4de2 | 10 | * |
<> | 154:37f96f9d4de2 | 11 | * o Redistributions in binary form must reproduce the above copyright notice, this |
<> | 154:37f96f9d4de2 | 12 | * list of conditions and the following disclaimer in the documentation and/or |
<> | 154:37f96f9d4de2 | 13 | * other materials provided with the distribution. |
<> | 154:37f96f9d4de2 | 14 | * |
<> | 154:37f96f9d4de2 | 15 | * o Neither the name of Freescale Semiconductor, Inc. nor the names of its |
<> | 154:37f96f9d4de2 | 16 | * contributors may be used to endorse or promote products derived from this |
<> | 154:37f96f9d4de2 | 17 | * software without specific prior written permission. |
<> | 154:37f96f9d4de2 | 18 | * |
<> | 154:37f96f9d4de2 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
<> | 154:37f96f9d4de2 | 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
<> | 154:37f96f9d4de2 | 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
<> | 154:37f96f9d4de2 | 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
<> | 154:37f96f9d4de2 | 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
<> | 154:37f96f9d4de2 | 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
<> | 154:37f96f9d4de2 | 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
<> | 154:37f96f9d4de2 | 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
<> | 154:37f96f9d4de2 | 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
<> | 154:37f96f9d4de2 | 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
<> | 154:37f96f9d4de2 | 29 | */ |
<> | 154:37f96f9d4de2 | 30 | |
<> | 154:37f96f9d4de2 | 31 | #include "fsl_enet.h" |
<> | 154:37f96f9d4de2 | 32 | |
<> | 154:37f96f9d4de2 | 33 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 34 | * Definitions |
<> | 154:37f96f9d4de2 | 35 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 36 | |
<> | 154:37f96f9d4de2 | 37 | /*! @brief IPv4 PTP message IP version offset. */ |
<> | 154:37f96f9d4de2 | 38 | #define ENET_PTP1588_IPVERSION_OFFSET 0x0EU |
<> | 154:37f96f9d4de2 | 39 | /*! @brief IPv4 PTP message UDP protocol offset. */ |
<> | 154:37f96f9d4de2 | 40 | #define ENET_PTP1588_IPV4_UDP_PROTOCOL_OFFSET 0x17U |
<> | 154:37f96f9d4de2 | 41 | /*! @brief IPv4 PTP message UDP port offset. */ |
<> | 154:37f96f9d4de2 | 42 | #define ENET_PTP1588_IPV4_UDP_PORT_OFFSET 0x24U |
<> | 154:37f96f9d4de2 | 43 | /*! @brief IPv4 PTP message UDP message type offset. */ |
<> | 154:37f96f9d4de2 | 44 | #define ENET_PTP1588_IPV4_UDP_MSGTYPE_OFFSET 0x2AU |
<> | 154:37f96f9d4de2 | 45 | /*! @brief IPv4 PTP message UDP version offset. */ |
<> | 154:37f96f9d4de2 | 46 | #define ENET_PTP1588_IPV4_UDP_VERSION_OFFSET 0x2BU |
<> | 154:37f96f9d4de2 | 47 | /*! @brief IPv4 PTP message UDP clock id offset. */ |
<> | 154:37f96f9d4de2 | 48 | #define ENET_PTP1588_IPV4_UDP_CLKID_OFFSET 0x3EU |
<> | 154:37f96f9d4de2 | 49 | /*! @brief IPv4 PTP message UDP sequence id offset. */ |
<> | 154:37f96f9d4de2 | 50 | #define ENET_PTP1588_IPV4_UDP_SEQUENCEID_OFFSET 0x48U |
<> | 154:37f96f9d4de2 | 51 | /*! @brief IPv4 PTP message UDP control offset. */ |
<> | 154:37f96f9d4de2 | 52 | #define ENET_PTP1588_IPV4_UDP_CTL_OFFSET 0x4AU |
<> | 154:37f96f9d4de2 | 53 | /*! @brief IPv6 PTP message UDP protocol offset. */ |
<> | 154:37f96f9d4de2 | 54 | #define ENET_PTP1588_IPV6_UDP_PROTOCOL_OFFSET 0x14U |
<> | 154:37f96f9d4de2 | 55 | /*! @brief IPv6 PTP message UDP port offset. */ |
<> | 154:37f96f9d4de2 | 56 | #define ENET_PTP1588_IPV6_UDP_PORT_OFFSET 0x38U |
<> | 154:37f96f9d4de2 | 57 | /*! @brief IPv6 PTP message UDP message type offset. */ |
<> | 154:37f96f9d4de2 | 58 | #define ENET_PTP1588_IPV6_UDP_MSGTYPE_OFFSET 0x3EU |
<> | 154:37f96f9d4de2 | 59 | /*! @brief IPv6 PTP message UDP version offset. */ |
<> | 154:37f96f9d4de2 | 60 | #define ENET_PTP1588_IPV6_UDP_VERSION_OFFSET 0x3FU |
<> | 154:37f96f9d4de2 | 61 | /*! @brief IPv6 PTP message UDP clock id offset. */ |
<> | 154:37f96f9d4de2 | 62 | #define ENET_PTP1588_IPV6_UDP_CLKID_OFFSET 0x52U |
<> | 154:37f96f9d4de2 | 63 | /*! @brief IPv6 PTP message UDP sequence id offset. */ |
<> | 154:37f96f9d4de2 | 64 | #define ENET_PTP1588_IPV6_UDP_SEQUENCEID_OFFSET 0x5CU |
<> | 154:37f96f9d4de2 | 65 | /*! @brief IPv6 PTP message UDP control offset. */ |
<> | 154:37f96f9d4de2 | 66 | #define ENET_PTP1588_IPV6_UDP_CTL_OFFSET 0x5EU |
<> | 154:37f96f9d4de2 | 67 | /*! @brief PTPv2 message Ethernet packet type offset. */ |
<> | 154:37f96f9d4de2 | 68 | #define ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET 0x0CU |
<> | 154:37f96f9d4de2 | 69 | /*! @brief PTPv2 message Ethernet message type offset. */ |
<> | 154:37f96f9d4de2 | 70 | #define ENET_PTP1588_ETHL2_MSGTYPE_OFFSET 0x0EU |
<> | 154:37f96f9d4de2 | 71 | /*! @brief PTPv2 message Ethernet version type offset. */ |
<> | 154:37f96f9d4de2 | 72 | #define ENET_PTP1588_ETHL2_VERSION_OFFSET 0X0FU |
<> | 154:37f96f9d4de2 | 73 | /*! @brief PTPv2 message Ethernet clock id offset. */ |
<> | 154:37f96f9d4de2 | 74 | #define ENET_PTP1588_ETHL2_CLOCKID_OFFSET 0x22 |
<> | 154:37f96f9d4de2 | 75 | /*! @brief PTPv2 message Ethernet sequence id offset. */ |
<> | 154:37f96f9d4de2 | 76 | #define ENET_PTP1588_ETHL2_SEQUENCEID_OFFSET 0x2c |
<> | 154:37f96f9d4de2 | 77 | /*! @brief Packet type Ethernet IEEE802.3 for PTPv2. */ |
<> | 154:37f96f9d4de2 | 78 | #define ENET_ETHERNETL2 0x88F7U |
<> | 154:37f96f9d4de2 | 79 | /*! @brief Packet type IPv4. */ |
<> | 154:37f96f9d4de2 | 80 | #define ENET_IPV4 0x0800U |
<> | 154:37f96f9d4de2 | 81 | /*! @brief Packet type IPv6. */ |
<> | 154:37f96f9d4de2 | 82 | #define ENET_IPV6 0x86ddU |
<> | 154:37f96f9d4de2 | 83 | /*! @brief Packet type VLAN. */ |
<> | 154:37f96f9d4de2 | 84 | #define ENET_8021QVLAN 0x8100U |
<> | 154:37f96f9d4de2 | 85 | /*! @brief UDP protocol type. */ |
<> | 154:37f96f9d4de2 | 86 | #define ENET_UDPVERSION 0x0011U |
<> | 154:37f96f9d4de2 | 87 | /*! @brief Packet IP version IPv4. */ |
<> | 154:37f96f9d4de2 | 88 | #define ENET_IPV4VERSION 0x0004U |
<> | 154:37f96f9d4de2 | 89 | /*! @brief Packet IP version IPv6. */ |
<> | 154:37f96f9d4de2 | 90 | #define ENET_IPV6VERSION 0x0006U |
<> | 154:37f96f9d4de2 | 91 | /*! @brief Ethernet mac address length. */ |
<> | 154:37f96f9d4de2 | 92 | #define ENET_FRAME_MACLEN 6U |
<> | 154:37f96f9d4de2 | 93 | /*! @brief Ethernet Frame header length. */ |
<> | 154:37f96f9d4de2 | 94 | #define ENET_FRAME_HEADERLEN 14U |
<> | 154:37f96f9d4de2 | 95 | /*! @brief Ethernet VLAN header length. */ |
<> | 154:37f96f9d4de2 | 96 | #define ENET_FRAME_VLAN_HEADERLEN 18U |
<> | 154:37f96f9d4de2 | 97 | /*! @brief MDC frequency. */ |
<> | 154:37f96f9d4de2 | 98 | #define ENET_MDC_FREQUENCY 2500000U |
<> | 154:37f96f9d4de2 | 99 | /*! @brief NanoSecond in one second. */ |
<> | 154:37f96f9d4de2 | 100 | #define ENET_NANOSECOND_ONE_SECOND 1000000000U |
<> | 154:37f96f9d4de2 | 101 | /*! @brief Define a common clock cycle delays used for time stamp capture. */ |
<> | 154:37f96f9d4de2 | 102 | #define ENET_1588TIME_DELAY_COUNT 10U |
<> | 154:37f96f9d4de2 | 103 | /*! @brief Defines the macro for converting constants from host byte order to network byte order. */ |
<> | 154:37f96f9d4de2 | 104 | #define ENET_HTONS(n) __REV16(n) |
<> | 154:37f96f9d4de2 | 105 | #define ENET_HTONL(n) __REV(n) |
<> | 154:37f96f9d4de2 | 106 | #define ENET_NTOHS(n) __REV16(n) |
<> | 154:37f96f9d4de2 | 107 | #define ENET_NTOHL(n) __REV(n) |
<> | 154:37f96f9d4de2 | 108 | |
<> | 154:37f96f9d4de2 | 109 | /* Typedef for interrupt handler. */ |
<> | 154:37f96f9d4de2 | 110 | typedef void (*enet_isr_t)(ENET_Type *base, enet_handle_t *handle); |
<> | 154:37f96f9d4de2 | 111 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 112 | * Prototypes |
<> | 154:37f96f9d4de2 | 113 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 114 | |
<> | 154:37f96f9d4de2 | 115 | /*! |
<> | 154:37f96f9d4de2 | 116 | * @brief Get the ENET instance from peripheral base address. |
<> | 154:37f96f9d4de2 | 117 | * |
<> | 154:37f96f9d4de2 | 118 | * @param base ENET peripheral base address. |
<> | 154:37f96f9d4de2 | 119 | * @return ENET instance. |
<> | 154:37f96f9d4de2 | 120 | */ |
<> | 154:37f96f9d4de2 | 121 | uint32_t ENET_GetInstance(ENET_Type *base); |
<> | 154:37f96f9d4de2 | 122 | |
<> | 154:37f96f9d4de2 | 123 | /*! |
<> | 154:37f96f9d4de2 | 124 | * @brief Set ENET MAC controller with the configuration. |
<> | 154:37f96f9d4de2 | 125 | * |
<> | 154:37f96f9d4de2 | 126 | * @param base ENET peripheral base address. |
<> | 154:37f96f9d4de2 | 127 | * @param config ENET Mac configuration. |
<> | 154:37f96f9d4de2 | 128 | * @param bufferConfig ENET buffer configuration. |
<> | 154:37f96f9d4de2 | 129 | * @param macAddr ENET six-byte mac address. |
<> | 154:37f96f9d4de2 | 130 | * @param srcClock_Hz ENET module clock source, normally it's system clock. |
<> | 154:37f96f9d4de2 | 131 | */ |
<> | 154:37f96f9d4de2 | 132 | static void ENET_SetMacController(ENET_Type *base, |
<> | 154:37f96f9d4de2 | 133 | const enet_config_t *config, |
<> | 154:37f96f9d4de2 | 134 | const enet_buffer_config_t *bufferConfig, |
<> | 154:37f96f9d4de2 | 135 | uint8_t *macAddr, |
<> | 154:37f96f9d4de2 | 136 | uint32_t srcClock_Hz); |
<> | 156:95d6b41a828b | 137 | /*! |
<> | 156:95d6b41a828b | 138 | * @brief Set ENET handler. |
<> | 156:95d6b41a828b | 139 | * |
<> | 156:95d6b41a828b | 140 | * @param base ENET peripheral base address. |
<> | 156:95d6b41a828b | 141 | * @param handle The ENET handle pointer. |
<> | 156:95d6b41a828b | 142 | * @param config ENET configuration stucture pointer. |
<> | 156:95d6b41a828b | 143 | * @param bufferConfig ENET buffer configuration. |
<> | 156:95d6b41a828b | 144 | */ |
<> | 156:95d6b41a828b | 145 | static void ENET_SetHandler(ENET_Type *base, |
<> | 156:95d6b41a828b | 146 | enet_handle_t *handle, |
<> | 156:95d6b41a828b | 147 | const enet_config_t *config, |
<> | 156:95d6b41a828b | 148 | const enet_buffer_config_t *bufferConfig); |
<> | 154:37f96f9d4de2 | 149 | /*! |
<> | 154:37f96f9d4de2 | 150 | * @brief Set ENET MAC transmit buffer descriptors. |
<> | 154:37f96f9d4de2 | 151 | * |
<> | 154:37f96f9d4de2 | 152 | * @param txBdStartAlign The aligned start address of ENET transmit buffer descriptors. |
<> | 154:37f96f9d4de2 | 153 | * is recommended to evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 154 | * @param txBuffStartAlign The aligned start address of ENET transmit buffers, must be evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 155 | * @param txBuffSizeAlign The aligned ENET transmit buffer size, must be evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 156 | * @param txBdNumber The number of ENET transmit buffers. |
<> | 154:37f96f9d4de2 | 157 | */ |
<> | 154:37f96f9d4de2 | 158 | static void ENET_SetTxBufferDescriptors(volatile enet_tx_bd_struct_t *txBdStartAlign, |
<> | 154:37f96f9d4de2 | 159 | uint8_t *txBuffStartAlign, |
<> | 154:37f96f9d4de2 | 160 | uint32_t txBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 161 | uint32_t txBdNumber); |
<> | 154:37f96f9d4de2 | 162 | |
<> | 154:37f96f9d4de2 | 163 | /*! |
<> | 154:37f96f9d4de2 | 164 | * @brief Set ENET MAC receive buffer descriptors. |
<> | 154:37f96f9d4de2 | 165 | * |
<> | 154:37f96f9d4de2 | 166 | * @param rxBdStartAlign The aligned start address of ENET receive buffer descriptors. |
<> | 154:37f96f9d4de2 | 167 | * is recommended to evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 168 | * @param rxBuffStartAlign The aligned start address of ENET receive buffers, must be evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 169 | * @param rxBuffSizeAlign The aligned ENET receive buffer size, must be evenly divisible by 16. |
<> | 154:37f96f9d4de2 | 170 | * @param rxBdNumber The number of ENET receive buffers. |
<> | 154:37f96f9d4de2 | 171 | * @param enableInterrupt Enable/disables to generate the receive byte and frame interrupt. |
<> | 154:37f96f9d4de2 | 172 | * It's used for ENET_ENHANCEDBUFFERDESCRIPTOR_MODE enabled case. |
<> | 154:37f96f9d4de2 | 173 | */ |
<> | 154:37f96f9d4de2 | 174 | static void ENET_SetRxBufferDescriptors(volatile enet_rx_bd_struct_t *rxBdStartAlign, |
<> | 154:37f96f9d4de2 | 175 | uint8_t *rxBuffStartAlign, |
<> | 154:37f96f9d4de2 | 176 | uint32_t rxBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 177 | uint32_t rxBdNumber, |
<> | 154:37f96f9d4de2 | 178 | bool enableInterrupt); |
<> | 154:37f96f9d4de2 | 179 | |
<> | 154:37f96f9d4de2 | 180 | /*! |
<> | 154:37f96f9d4de2 | 181 | * @brief Updates the ENET read buffer descriptors. |
<> | 154:37f96f9d4de2 | 182 | * |
<> | 154:37f96f9d4de2 | 183 | * @param base ENET peripheral base address. |
<> | 154:37f96f9d4de2 | 184 | * @param handle The ENET handle pointer. |
<> | 154:37f96f9d4de2 | 185 | */ |
<> | 154:37f96f9d4de2 | 186 | static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle); |
<> | 154:37f96f9d4de2 | 187 | |
<> | 154:37f96f9d4de2 | 188 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 189 | /*! |
<> | 154:37f96f9d4de2 | 190 | * @brief Parses the ENET frame for time-stamp process of PTP 1588 frame. |
<> | 154:37f96f9d4de2 | 191 | * |
<> | 154:37f96f9d4de2 | 192 | * @param data The ENET read data for frame parse. |
<> | 154:37f96f9d4de2 | 193 | * @param ptpTsData The ENET PTP message and time-stamp data pointer. |
<> | 154:37f96f9d4de2 | 194 | * @param isFastEnabled The fast parse flag. |
<> | 154:37f96f9d4de2 | 195 | * - true , Fast processing, only check if this is a PTP message. |
<> | 154:37f96f9d4de2 | 196 | * - false, Store the PTP message data after check the PTP message. |
<> | 154:37f96f9d4de2 | 197 | */ |
<> | 154:37f96f9d4de2 | 198 | static bool ENET_Ptp1588ParseFrame(uint8_t *data, enet_ptp_time_data_t *ptpTsData, bool isFastEnabled); |
<> | 154:37f96f9d4de2 | 199 | |
<> | 154:37f96f9d4de2 | 200 | /*! |
<> | 154:37f96f9d4de2 | 201 | * @brief Updates the new PTP 1588 time-stamp to the time-stamp buffer ring. |
<> | 154:37f96f9d4de2 | 202 | * |
<> | 154:37f96f9d4de2 | 203 | * @param ptpTsDataRing The PTP message and time-stamp data ring pointer. |
<> | 154:37f96f9d4de2 | 204 | * @param ptpTimeData The new PTP 1588 time-stamp data pointer. |
<> | 154:37f96f9d4de2 | 205 | */ |
<> | 154:37f96f9d4de2 | 206 | static status_t ENET_Ptp1588UpdateTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimeData); |
<> | 154:37f96f9d4de2 | 207 | |
<> | 154:37f96f9d4de2 | 208 | /*! |
<> | 154:37f96f9d4de2 | 209 | * @brief Search up the right PTP 1588 time-stamp from the time-stamp buffer ring. |
<> | 154:37f96f9d4de2 | 210 | * |
<> | 154:37f96f9d4de2 | 211 | * @param ptpTsDataRing The PTP message and time-stamp data ring pointer. |
<> | 154:37f96f9d4de2 | 212 | * @param ptpTimeData The find out right PTP 1588 time-stamp data pointer with the specific PTP message. |
<> | 154:37f96f9d4de2 | 213 | */ |
<> | 154:37f96f9d4de2 | 214 | static status_t ENET_Ptp1588SearchTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimedata); |
<> | 154:37f96f9d4de2 | 215 | |
<> | 154:37f96f9d4de2 | 216 | /*! |
<> | 154:37f96f9d4de2 | 217 | * @brief Store the transmit time-stamp for event PTP frame in the time-stamp buffer ring. |
<> | 154:37f96f9d4de2 | 218 | * |
<> | 154:37f96f9d4de2 | 219 | * @param base ENET peripheral base address. |
<> | 154:37f96f9d4de2 | 220 | * @param handle The ENET handle pointer. |
<> | 154:37f96f9d4de2 | 221 | */ |
<> | 154:37f96f9d4de2 | 222 | static status_t ENET_StoreTxFrameTime(ENET_Type *base, enet_handle_t *handle); |
<> | 154:37f96f9d4de2 | 223 | |
<> | 154:37f96f9d4de2 | 224 | /*! |
<> | 154:37f96f9d4de2 | 225 | * @brief Store the receive time-stamp for event PTP frame in the time-stamp buffer ring. |
<> | 154:37f96f9d4de2 | 226 | * |
<> | 154:37f96f9d4de2 | 227 | * @param base ENET peripheral base address. |
<> | 154:37f96f9d4de2 | 228 | * @param handle The ENET handle pointer. |
<> | 154:37f96f9d4de2 | 229 | * @param ptpTimeData The PTP 1588 time-stamp data pointer. |
<> | 154:37f96f9d4de2 | 230 | */ |
<> | 154:37f96f9d4de2 | 231 | static status_t ENET_StoreRxFrameTime(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData); |
<> | 154:37f96f9d4de2 | 232 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 233 | |
<> | 154:37f96f9d4de2 | 234 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 235 | * Variables |
<> | 154:37f96f9d4de2 | 236 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 237 | |
<> | 154:37f96f9d4de2 | 238 | /*! @brief Pointers to enet handles for each instance. */ |
<> | 154:37f96f9d4de2 | 239 | static enet_handle_t *s_ENETHandle[FSL_FEATURE_SOC_ENET_COUNT] = {NULL}; |
<> | 154:37f96f9d4de2 | 240 | |
<> | 154:37f96f9d4de2 | 241 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 242 | /*! @brief Pointers to enet clocks for each instance. */ |
<> | 156:95d6b41a828b | 243 | const clock_ip_name_t s_enetClock[] = ENET_CLOCKS; |
<> | 154:37f96f9d4de2 | 244 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 245 | |
<> | 154:37f96f9d4de2 | 246 | /*! @brief Pointers to enet transmit IRQ number for each instance. */ |
<> | 154:37f96f9d4de2 | 247 | static const IRQn_Type s_enetTxIrqId[] = ENET_Transmit_IRQS; |
<> | 154:37f96f9d4de2 | 248 | /*! @brief Pointers to enet receive IRQ number for each instance. */ |
<> | 154:37f96f9d4de2 | 249 | static const IRQn_Type s_enetRxIrqId[] = ENET_Receive_IRQS; |
<> | 154:37f96f9d4de2 | 250 | #if defined(ENET_ENHANCEDBUFFERDESCRIPTOR_MODE) && ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 251 | /*! @brief Pointers to enet timestamp IRQ number for each instance. */ |
<> | 154:37f96f9d4de2 | 252 | static const IRQn_Type s_enetTsIrqId[] = ENET_1588_Timer_IRQS; |
<> | 154:37f96f9d4de2 | 253 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 254 | /*! @brief Pointers to enet error IRQ number for each instance. */ |
<> | 154:37f96f9d4de2 | 255 | static const IRQn_Type s_enetErrIrqId[] = ENET_Error_IRQS; |
<> | 154:37f96f9d4de2 | 256 | |
<> | 154:37f96f9d4de2 | 257 | /*! @brief Pointers to enet bases for each instance. */ |
<> | 154:37f96f9d4de2 | 258 | static ENET_Type *const s_enetBases[] = ENET_BASE_PTRS; |
<> | 154:37f96f9d4de2 | 259 | |
<> | 154:37f96f9d4de2 | 260 | /* ENET ISR for transactional APIs. */ |
<> | 154:37f96f9d4de2 | 261 | static enet_isr_t s_enetTxIsr; |
<> | 154:37f96f9d4de2 | 262 | static enet_isr_t s_enetRxIsr; |
<> | 154:37f96f9d4de2 | 263 | static enet_isr_t s_enetErrIsr; |
<> | 154:37f96f9d4de2 | 264 | /******************************************************************************* |
<> | 154:37f96f9d4de2 | 265 | * Code |
<> | 154:37f96f9d4de2 | 266 | ******************************************************************************/ |
<> | 154:37f96f9d4de2 | 267 | |
<> | 154:37f96f9d4de2 | 268 | uint32_t ENET_GetInstance(ENET_Type *base) |
<> | 154:37f96f9d4de2 | 269 | { |
<> | 154:37f96f9d4de2 | 270 | uint32_t instance; |
<> | 154:37f96f9d4de2 | 271 | |
<> | 154:37f96f9d4de2 | 272 | /* Find the instance index from base address mappings. */ |
<> | 154:37f96f9d4de2 | 273 | for (instance = 0; instance < FSL_FEATURE_SOC_ENET_COUNT; instance++) |
<> | 154:37f96f9d4de2 | 274 | { |
<> | 154:37f96f9d4de2 | 275 | if (s_enetBases[instance] == base) |
<> | 154:37f96f9d4de2 | 276 | { |
<> | 154:37f96f9d4de2 | 277 | break; |
<> | 154:37f96f9d4de2 | 278 | } |
<> | 154:37f96f9d4de2 | 279 | } |
<> | 154:37f96f9d4de2 | 280 | |
<> | 154:37f96f9d4de2 | 281 | assert(instance < FSL_FEATURE_SOC_ENET_COUNT); |
<> | 154:37f96f9d4de2 | 282 | |
<> | 154:37f96f9d4de2 | 283 | return instance; |
<> | 154:37f96f9d4de2 | 284 | } |
<> | 154:37f96f9d4de2 | 285 | |
<> | 154:37f96f9d4de2 | 286 | void ENET_GetDefaultConfig(enet_config_t *config) |
<> | 154:37f96f9d4de2 | 287 | { |
<> | 154:37f96f9d4de2 | 288 | /* Checks input parameter. */ |
<> | 154:37f96f9d4de2 | 289 | assert(config); |
<> | 154:37f96f9d4de2 | 290 | |
<> | 154:37f96f9d4de2 | 291 | /* Initializes the MAC configure structure to zero. */ |
<> | 154:37f96f9d4de2 | 292 | memset(config, 0, sizeof(enet_config_t)); |
<> | 154:37f96f9d4de2 | 293 | |
<> | 154:37f96f9d4de2 | 294 | /* Sets MII mode, full duplex, 100Mbps for MAC and PHY data interface. */ |
<> | 154:37f96f9d4de2 | 295 | config->miiMode = kENET_RmiiMode; |
<> | 154:37f96f9d4de2 | 296 | config->miiSpeed = kENET_MiiSpeed100M; |
<> | 154:37f96f9d4de2 | 297 | config->miiDuplex = kENET_MiiFullDuplex; |
<> | 154:37f96f9d4de2 | 298 | |
<> | 154:37f96f9d4de2 | 299 | /* Sets the maximum receive frame length. */ |
<> | 154:37f96f9d4de2 | 300 | config->rxMaxFrameLen = ENET_FRAME_MAX_FRAMELEN; |
<> | 154:37f96f9d4de2 | 301 | } |
<> | 154:37f96f9d4de2 | 302 | |
<> | 154:37f96f9d4de2 | 303 | void ENET_Init(ENET_Type *base, |
<> | 154:37f96f9d4de2 | 304 | enet_handle_t *handle, |
<> | 154:37f96f9d4de2 | 305 | const enet_config_t *config, |
<> | 154:37f96f9d4de2 | 306 | const enet_buffer_config_t *bufferConfig, |
<> | 154:37f96f9d4de2 | 307 | uint8_t *macAddr, |
<> | 154:37f96f9d4de2 | 308 | uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 309 | { |
<> | 154:37f96f9d4de2 | 310 | /* Checks input parameters. */ |
<> | 154:37f96f9d4de2 | 311 | assert(handle); |
<> | 154:37f96f9d4de2 | 312 | assert(config); |
<> | 154:37f96f9d4de2 | 313 | assert(bufferConfig); |
<> | 154:37f96f9d4de2 | 314 | assert(bufferConfig->rxBdStartAddrAlign); |
<> | 154:37f96f9d4de2 | 315 | assert(bufferConfig->txBdStartAddrAlign); |
<> | 154:37f96f9d4de2 | 316 | assert(bufferConfig->rxBufferAlign); |
<> | 154:37f96f9d4de2 | 317 | assert(macAddr); |
<> | 154:37f96f9d4de2 | 318 | |
<> | 154:37f96f9d4de2 | 319 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
Kojto | 169:e3b6fe271b81 | 320 | uint32_t instance = ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 321 | /* Ungate ENET clock. */ |
<> | 154:37f96f9d4de2 | 322 | CLOCK_EnableClock(s_enetClock[instance]); |
<> | 154:37f96f9d4de2 | 323 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 324 | |
<> | 154:37f96f9d4de2 | 325 | /* Reset ENET module. */ |
<> | 154:37f96f9d4de2 | 326 | ENET_Reset(base); |
<> | 154:37f96f9d4de2 | 327 | |
<> | 154:37f96f9d4de2 | 328 | /* Initializes the ENET transmit buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 329 | ENET_SetTxBufferDescriptors(bufferConfig->txBdStartAddrAlign, bufferConfig->txBufferAlign, |
<> | 154:37f96f9d4de2 | 330 | bufferConfig->txBuffSizeAlign, bufferConfig->txBdNumber); |
<> | 154:37f96f9d4de2 | 331 | |
<> | 154:37f96f9d4de2 | 332 | /* Initializes the ENET receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 333 | ENET_SetRxBufferDescriptors(bufferConfig->rxBdStartAddrAlign, bufferConfig->rxBufferAlign, |
<> | 154:37f96f9d4de2 | 334 | bufferConfig->rxBuffSizeAlign, bufferConfig->rxBdNumber, |
<> | 154:37f96f9d4de2 | 335 | !!(config->interrupt & (kENET_RxFrameInterrupt | kENET_RxBufferInterrupt))); |
<> | 154:37f96f9d4de2 | 336 | |
<> | 154:37f96f9d4de2 | 337 | /* Initializes the ENET MAC controller. */ |
<> | 154:37f96f9d4de2 | 338 | ENET_SetMacController(base, config, bufferConfig, macAddr, srcClock_Hz); |
<> | 154:37f96f9d4de2 | 339 | |
<> | 156:95d6b41a828b | 340 | /* Set all buffers or data in handler for data transmit/receive process. */ |
<> | 156:95d6b41a828b | 341 | ENET_SetHandler(base, handle, config, bufferConfig); |
<> | 154:37f96f9d4de2 | 342 | } |
<> | 154:37f96f9d4de2 | 343 | |
<> | 154:37f96f9d4de2 | 344 | void ENET_Deinit(ENET_Type *base) |
<> | 154:37f96f9d4de2 | 345 | { |
<> | 154:37f96f9d4de2 | 346 | /* Disable interrupt. */ |
<> | 154:37f96f9d4de2 | 347 | base->EIMR = 0; |
<> | 154:37f96f9d4de2 | 348 | |
<> | 154:37f96f9d4de2 | 349 | /* Disable ENET. */ |
<> | 154:37f96f9d4de2 | 350 | base->ECR &= ~ENET_ECR_ETHEREN_MASK; |
<> | 154:37f96f9d4de2 | 351 | |
<> | 154:37f96f9d4de2 | 352 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 353 | /* Disables the clock source. */ |
<> | 154:37f96f9d4de2 | 354 | CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 355 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 356 | } |
<> | 154:37f96f9d4de2 | 357 | |
<> | 154:37f96f9d4de2 | 358 | void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *userData) |
<> | 154:37f96f9d4de2 | 359 | { |
<> | 154:37f96f9d4de2 | 360 | assert(handle); |
<> | 154:37f96f9d4de2 | 361 | |
<> | 154:37f96f9d4de2 | 362 | /* Set callback and userData. */ |
<> | 154:37f96f9d4de2 | 363 | handle->callback = callback; |
<> | 154:37f96f9d4de2 | 364 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 365 | } |
<> | 154:37f96f9d4de2 | 366 | |
<> | 156:95d6b41a828b | 367 | static void ENET_SetHandler(ENET_Type *base, |
<> | 156:95d6b41a828b | 368 | enet_handle_t *handle, |
<> | 156:95d6b41a828b | 369 | const enet_config_t *config, |
<> | 156:95d6b41a828b | 370 | const enet_buffer_config_t *bufferConfig) |
<> | 156:95d6b41a828b | 371 | { |
<> | 156:95d6b41a828b | 372 | uint32_t instance = ENET_GetInstance(base); |
<> | 156:95d6b41a828b | 373 | |
<> | 156:95d6b41a828b | 374 | memset(handle, 0, sizeof(enet_handle_t)); |
<> | 156:95d6b41a828b | 375 | |
<> | 156:95d6b41a828b | 376 | handle->rxBdBase = bufferConfig->rxBdStartAddrAlign; |
<> | 156:95d6b41a828b | 377 | handle->rxBdCurrent = bufferConfig->rxBdStartAddrAlign; |
<> | 156:95d6b41a828b | 378 | handle->txBdBase = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 379 | handle->txBdCurrent = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 380 | handle->txBdDirty = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 381 | handle->rxBuffSizeAlign = bufferConfig->rxBuffSizeAlign; |
<> | 156:95d6b41a828b | 382 | handle->txBuffSizeAlign = bufferConfig->txBuffSizeAlign; |
<> | 156:95d6b41a828b | 383 | |
<> | 156:95d6b41a828b | 384 | /* Save the handle pointer in the global variables. */ |
<> | 156:95d6b41a828b | 385 | s_ENETHandle[instance] = handle; |
<> | 156:95d6b41a828b | 386 | |
<> | 156:95d6b41a828b | 387 | /* Set the IRQ handler when the interrupt is enabled. */ |
<> | 156:95d6b41a828b | 388 | if (config->interrupt & ENET_TX_INTERRUPT) |
<> | 156:95d6b41a828b | 389 | { |
<> | 156:95d6b41a828b | 390 | s_enetTxIsr = ENET_TransmitIRQHandler; |
<> | 156:95d6b41a828b | 391 | EnableIRQ(s_enetTxIrqId[instance]); |
<> | 156:95d6b41a828b | 392 | } |
<> | 156:95d6b41a828b | 393 | if (config->interrupt & ENET_RX_INTERRUPT) |
<> | 156:95d6b41a828b | 394 | { |
<> | 156:95d6b41a828b | 395 | s_enetRxIsr = ENET_ReceiveIRQHandler; |
<> | 156:95d6b41a828b | 396 | EnableIRQ(s_enetRxIrqId[instance]); |
<> | 156:95d6b41a828b | 397 | } |
<> | 156:95d6b41a828b | 398 | if (config->interrupt & ENET_ERR_INTERRUPT) |
<> | 156:95d6b41a828b | 399 | { |
<> | 156:95d6b41a828b | 400 | s_enetErrIsr = ENET_ErrorIRQHandler; |
<> | 156:95d6b41a828b | 401 | EnableIRQ(s_enetErrIrqId[instance]); |
<> | 156:95d6b41a828b | 402 | } |
<> | 156:95d6b41a828b | 403 | } |
<> | 156:95d6b41a828b | 404 | |
<> | 154:37f96f9d4de2 | 405 | static void ENET_SetMacController(ENET_Type *base, |
<> | 154:37f96f9d4de2 | 406 | const enet_config_t *config, |
<> | 154:37f96f9d4de2 | 407 | const enet_buffer_config_t *bufferConfig, |
<> | 154:37f96f9d4de2 | 408 | uint8_t *macAddr, |
<> | 154:37f96f9d4de2 | 409 | uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 410 | { |
<> | 154:37f96f9d4de2 | 411 | uint32_t rcr = 0; |
<> | 154:37f96f9d4de2 | 412 | uint32_t tcr = 0; |
<> | 154:37f96f9d4de2 | 413 | uint32_t ecr = 0; |
<> | 154:37f96f9d4de2 | 414 | uint32_t macSpecialConfig = config->macSpecialConfig; |
Kojto | 169:e3b6fe271b81 | 415 | ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 416 | |
<> | 154:37f96f9d4de2 | 417 | /* Configures MAC receive controller with user configure structure. */ |
<> | 154:37f96f9d4de2 | 418 | rcr = ENET_RCR_NLC(!!(macSpecialConfig & kENET_ControlRxPayloadCheckEnable)) | |
<> | 154:37f96f9d4de2 | 419 | ENET_RCR_CFEN(!!(macSpecialConfig & kENET_ControlFlowControlEnable)) | |
<> | 154:37f96f9d4de2 | 420 | ENET_RCR_FCE(!!(macSpecialConfig & kENET_ControlFlowControlEnable)) | |
<> | 154:37f96f9d4de2 | 421 | ENET_RCR_PADEN(!!(macSpecialConfig & kENET_ControlRxPadRemoveEnable)) | |
<> | 154:37f96f9d4de2 | 422 | ENET_RCR_BC_REJ(!!(macSpecialConfig & kENET_ControlRxBroadCastRejectEnable)) | |
<> | 154:37f96f9d4de2 | 423 | ENET_RCR_PROM(!!(macSpecialConfig & kENET_ControlPromiscuousEnable)) | ENET_RCR_MII_MODE(1) | |
<> | 154:37f96f9d4de2 | 424 | ENET_RCR_RMII_MODE(config->miiMode) | ENET_RCR_RMII_10T(!config->miiSpeed) | |
<> | 154:37f96f9d4de2 | 425 | ENET_RCR_MAX_FL(config->rxMaxFrameLen) | ENET_RCR_CRCFWD(1); |
<> | 154:37f96f9d4de2 | 426 | /* Receive setting for half duplex. */ |
<> | 154:37f96f9d4de2 | 427 | if (config->miiDuplex == kENET_MiiHalfDuplex) |
<> | 154:37f96f9d4de2 | 428 | { |
<> | 154:37f96f9d4de2 | 429 | rcr |= ENET_RCR_DRT(1); |
<> | 154:37f96f9d4de2 | 430 | } |
<> | 154:37f96f9d4de2 | 431 | /* Sets internal loop only for MII mode. */ |
<> | 154:37f96f9d4de2 | 432 | if ((config->macSpecialConfig & kENET_ControlMIILoopEnable) && (config->miiMode == kENET_MiiMode)) |
<> | 154:37f96f9d4de2 | 433 | { |
<> | 154:37f96f9d4de2 | 434 | rcr |= ENET_RCR_LOOP(1); |
<> | 154:37f96f9d4de2 | 435 | rcr &= ~ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 436 | } |
<> | 154:37f96f9d4de2 | 437 | base->RCR = rcr; |
<> | 154:37f96f9d4de2 | 438 | |
<> | 154:37f96f9d4de2 | 439 | /* Configures MAC transmit controller: duplex mode, mac address insertion. */ |
<> | 154:37f96f9d4de2 | 440 | tcr = base->TCR & ~(ENET_TCR_FDEN_MASK | ENET_TCR_ADDINS_MASK); |
<> | 154:37f96f9d4de2 | 441 | tcr |= ENET_TCR_FDEN(config->miiDuplex) | ENET_TCR_ADDINS(!!(macSpecialConfig & kENET_ControlMacAddrInsert)); |
<> | 154:37f96f9d4de2 | 442 | base->TCR = tcr; |
<> | 154:37f96f9d4de2 | 443 | |
<> | 154:37f96f9d4de2 | 444 | /* Configures receive and transmit accelerator. */ |
<> | 154:37f96f9d4de2 | 445 | base->TACC = config->txAccelerConfig; |
<> | 154:37f96f9d4de2 | 446 | base->RACC = config->rxAccelerConfig; |
<> | 154:37f96f9d4de2 | 447 | |
<> | 154:37f96f9d4de2 | 448 | /* Sets the pause duration and FIFO threshold for the flow control enabled case. */ |
<> | 154:37f96f9d4de2 | 449 | if (macSpecialConfig & kENET_ControlFlowControlEnable) |
<> | 154:37f96f9d4de2 | 450 | { |
<> | 154:37f96f9d4de2 | 451 | uint32_t reemReg; |
<> | 154:37f96f9d4de2 | 452 | base->OPD = config->pauseDuration; |
<> | 154:37f96f9d4de2 | 453 | reemReg = ENET_RSEM_RX_SECTION_EMPTY(config->rxFifoEmptyThreshold); |
<> | 154:37f96f9d4de2 | 454 | #if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD |
<> | 154:37f96f9d4de2 | 455 | reemReg |= ENET_RSEM_STAT_SECTION_EMPTY(config->rxFifoStatEmptyThreshold); |
<> | 154:37f96f9d4de2 | 456 | #endif /* FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD */ |
<> | 154:37f96f9d4de2 | 457 | base->RSEM = reemReg; |
<> | 154:37f96f9d4de2 | 458 | } |
<> | 154:37f96f9d4de2 | 459 | |
<> | 154:37f96f9d4de2 | 460 | /* FIFO threshold setting for store and forward enable/disable case. */ |
<> | 154:37f96f9d4de2 | 461 | if (macSpecialConfig & kENET_ControlStoreAndFwdDisable) |
<> | 154:37f96f9d4de2 | 462 | { |
<> | 154:37f96f9d4de2 | 463 | /* Transmit fifo watermark settings. */ |
<> | 154:37f96f9d4de2 | 464 | base->TFWR = config->txFifoWatermark & ENET_TFWR_TFWR_MASK; |
<> | 154:37f96f9d4de2 | 465 | /* Receive fifo full threshold settings. */ |
<> | 154:37f96f9d4de2 | 466 | base->RSFL = config->rxFifoFullThreshold & ENET_RSFL_RX_SECTION_FULL_MASK; |
<> | 154:37f96f9d4de2 | 467 | } |
<> | 154:37f96f9d4de2 | 468 | else |
<> | 154:37f96f9d4de2 | 469 | { |
<> | 154:37f96f9d4de2 | 470 | /* Transmit fifo watermark settings. */ |
<> | 154:37f96f9d4de2 | 471 | base->TFWR = ENET_TFWR_STRFWD_MASK; |
<> | 154:37f96f9d4de2 | 472 | base->RSFL = 0; |
<> | 154:37f96f9d4de2 | 473 | } |
<> | 154:37f96f9d4de2 | 474 | |
<> | 154:37f96f9d4de2 | 475 | /* Enable store and forward when accelerator is enabled */ |
<> | 154:37f96f9d4de2 | 476 | if (config->txAccelerConfig & (kENET_TxAccelIpCheckEnabled | kENET_TxAccelProtoCheckEnabled)) |
<> | 154:37f96f9d4de2 | 477 | { |
<> | 154:37f96f9d4de2 | 478 | base->TFWR = ENET_TFWR_STRFWD_MASK; |
<> | 154:37f96f9d4de2 | 479 | } |
<> | 154:37f96f9d4de2 | 480 | if (config->rxAccelerConfig & (kENET_RxAccelIpCheckEnabled | kENET_RxAccelProtoCheckEnabled)) |
<> | 154:37f96f9d4de2 | 481 | { |
<> | 154:37f96f9d4de2 | 482 | base->RSFL = 0; |
<> | 154:37f96f9d4de2 | 483 | } |
<> | 154:37f96f9d4de2 | 484 | |
<> | 154:37f96f9d4de2 | 485 | /* Initializes transmit buffer descriptor rings start address, two start address should be aligned. */ |
<> | 154:37f96f9d4de2 | 486 | base->TDSR = (uint32_t)bufferConfig->txBdStartAddrAlign; |
<> | 154:37f96f9d4de2 | 487 | base->RDSR = (uint32_t)bufferConfig->rxBdStartAddrAlign; |
<> | 154:37f96f9d4de2 | 488 | /* Initializes the maximum buffer size, the buffer size should be aligned. */ |
<> | 154:37f96f9d4de2 | 489 | base->MRBR = bufferConfig->rxBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 490 | |
<> | 154:37f96f9d4de2 | 491 | /* Configures the Mac address. */ |
<> | 154:37f96f9d4de2 | 492 | ENET_SetMacAddr(base, macAddr); |
<> | 154:37f96f9d4de2 | 493 | |
<> | 154:37f96f9d4de2 | 494 | /* Initialize the SMI if uninitialized. */ |
<> | 154:37f96f9d4de2 | 495 | if (!ENET_GetSMI(base)) |
<> | 154:37f96f9d4de2 | 496 | { |
<> | 154:37f96f9d4de2 | 497 | ENET_SetSMI(base, srcClock_Hz, !!(config->macSpecialConfig & kENET_ControlSMIPreambleDisable)); |
<> | 154:37f96f9d4de2 | 498 | } |
<> | 154:37f96f9d4de2 | 499 | |
<> | 154:37f96f9d4de2 | 500 | /* Enables Ethernet interrupt and NVIC. */ |
<> | 154:37f96f9d4de2 | 501 | ENET_EnableInterrupts(base, config->interrupt); |
<> | 154:37f96f9d4de2 | 502 | |
<> | 154:37f96f9d4de2 | 503 | /* ENET control register setting. */ |
<> | 154:37f96f9d4de2 | 504 | ecr = base->ECR; |
<> | 154:37f96f9d4de2 | 505 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 506 | /* Sets the 1588 enhanced feature. */ |
<> | 154:37f96f9d4de2 | 507 | ecr |= ENET_ECR_EN1588_MASK; |
<> | 154:37f96f9d4de2 | 508 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 509 | /* Enables Ethernet module after all configuration except the buffer descriptor active. */ |
<> | 154:37f96f9d4de2 | 510 | ecr |= ENET_ECR_ETHEREN_MASK | ENET_ECR_DBSWP_MASK; |
<> | 154:37f96f9d4de2 | 511 | base->ECR = ecr; |
<> | 154:37f96f9d4de2 | 512 | } |
<> | 154:37f96f9d4de2 | 513 | |
<> | 154:37f96f9d4de2 | 514 | static void ENET_SetTxBufferDescriptors(volatile enet_tx_bd_struct_t *txBdStartAlign, |
<> | 154:37f96f9d4de2 | 515 | uint8_t *txBuffStartAlign, |
<> | 154:37f96f9d4de2 | 516 | uint32_t txBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 517 | uint32_t txBdNumber) |
<> | 154:37f96f9d4de2 | 518 | { |
<> | 154:37f96f9d4de2 | 519 | assert(txBdStartAlign); |
<> | 154:37f96f9d4de2 | 520 | |
<> | 154:37f96f9d4de2 | 521 | uint32_t count; |
<> | 154:37f96f9d4de2 | 522 | volatile enet_tx_bd_struct_t *curBuffDescrip = txBdStartAlign; |
<> | 154:37f96f9d4de2 | 523 | |
<> | 154:37f96f9d4de2 | 524 | for (count = 0; count < txBdNumber; count++) |
<> | 154:37f96f9d4de2 | 525 | { |
<> | 156:95d6b41a828b | 526 | if (txBuffStartAlign != NULL) |
<> | 154:37f96f9d4de2 | 527 | { |
<> | 154:37f96f9d4de2 | 528 | /* Set data buffer address. */ |
<> | 154:37f96f9d4de2 | 529 | curBuffDescrip->buffer = (uint8_t *)((uint32_t)&txBuffStartAlign[count * txBuffSizeAlign]); |
<> | 154:37f96f9d4de2 | 530 | } |
<> | 154:37f96f9d4de2 | 531 | else |
<> | 154:37f96f9d4de2 | 532 | { |
<> | 154:37f96f9d4de2 | 533 | /* User should provide the transmit buffer at a later time */ |
<> | 154:37f96f9d4de2 | 534 | curBuffDescrip->buffer = NULL; |
<> | 154:37f96f9d4de2 | 535 | } |
<> | 154:37f96f9d4de2 | 536 | /* Initializes data length. */ |
<> | 154:37f96f9d4de2 | 537 | curBuffDescrip->length = 0; |
<> | 154:37f96f9d4de2 | 538 | /* Sets the crc. */ |
<> | 154:37f96f9d4de2 | 539 | curBuffDescrip->control = ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK; |
<> | 154:37f96f9d4de2 | 540 | /* Sets the last buffer descriptor with the wrap flag. */ |
<> | 154:37f96f9d4de2 | 541 | if (count == txBdNumber - 1) |
<> | 154:37f96f9d4de2 | 542 | { |
<> | 154:37f96f9d4de2 | 543 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 544 | } |
<> | 154:37f96f9d4de2 | 545 | |
<> | 154:37f96f9d4de2 | 546 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 547 | /* Enable transmit interrupt for store the transmit timestamp. */ |
<> | 154:37f96f9d4de2 | 548 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK; |
<> | 154:37f96f9d4de2 | 549 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 550 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 551 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 552 | } |
<> | 156:95d6b41a828b | 553 | |
<> | 154:37f96f9d4de2 | 554 | } |
<> | 154:37f96f9d4de2 | 555 | |
<> | 154:37f96f9d4de2 | 556 | static void ENET_SetRxBufferDescriptors(volatile enet_rx_bd_struct_t *rxBdStartAlign, |
<> | 154:37f96f9d4de2 | 557 | uint8_t *rxBuffStartAlign, |
<> | 154:37f96f9d4de2 | 558 | uint32_t rxBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 559 | uint32_t rxBdNumber, |
<> | 154:37f96f9d4de2 | 560 | bool enableInterrupt) |
<> | 154:37f96f9d4de2 | 561 | { |
<> | 154:37f96f9d4de2 | 562 | assert(rxBdStartAlign); |
<> | 154:37f96f9d4de2 | 563 | assert(rxBuffStartAlign); |
<> | 154:37f96f9d4de2 | 564 | |
<> | 154:37f96f9d4de2 | 565 | volatile enet_rx_bd_struct_t *curBuffDescrip = rxBdStartAlign; |
<> | 154:37f96f9d4de2 | 566 | uint32_t count = 0; |
<> | 154:37f96f9d4de2 | 567 | |
<> | 154:37f96f9d4de2 | 568 | /* Initializes receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 569 | for (count = 0; count < rxBdNumber; count++) |
<> | 154:37f96f9d4de2 | 570 | { |
<> | 154:37f96f9d4de2 | 571 | /* Set data buffer and the length. */ |
<> | 154:37f96f9d4de2 | 572 | curBuffDescrip->buffer = (uint8_t *)(*((uint32_t *)(rxBuffStartAlign + count * 4))); |
<> | 154:37f96f9d4de2 | 573 | curBuffDescrip->length = 0; |
<> | 154:37f96f9d4de2 | 574 | |
<> | 154:37f96f9d4de2 | 575 | /* Initializes the buffer descriptors with empty bit. */ |
<> | 154:37f96f9d4de2 | 576 | curBuffDescrip->control = ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 577 | /* Sets the last buffer descriptor with the wrap flag. */ |
<> | 154:37f96f9d4de2 | 578 | if (count == rxBdNumber - 1) |
<> | 154:37f96f9d4de2 | 579 | { |
<> | 154:37f96f9d4de2 | 580 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 581 | } |
<> | 154:37f96f9d4de2 | 582 | |
<> | 154:37f96f9d4de2 | 583 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 584 | if (enableInterrupt) |
<> | 154:37f96f9d4de2 | 585 | { |
<> | 154:37f96f9d4de2 | 586 | /* Enable receive interrupt. */ |
<> | 154:37f96f9d4de2 | 587 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_RX_INTERRUPT_MASK; |
<> | 154:37f96f9d4de2 | 588 | } |
<> | 154:37f96f9d4de2 | 589 | else |
<> | 154:37f96f9d4de2 | 590 | { |
<> | 154:37f96f9d4de2 | 591 | curBuffDescrip->controlExtend1 = 0; |
<> | 154:37f96f9d4de2 | 592 | } |
<> | 154:37f96f9d4de2 | 593 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 594 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 595 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 596 | } |
<> | 154:37f96f9d4de2 | 597 | } |
<> | 154:37f96f9d4de2 | 598 | |
<> | 154:37f96f9d4de2 | 599 | void ENET_SetMII(ENET_Type *base, enet_mii_speed_t speed, enet_mii_duplex_t duplex) |
<> | 154:37f96f9d4de2 | 600 | { |
<> | 156:95d6b41a828b | 601 | uint32_t rcr = base->RCR; |
<> | 156:95d6b41a828b | 602 | uint32_t tcr = base->TCR; |
<> | 154:37f96f9d4de2 | 603 | /* Sets speed mode. */ |
<> | 154:37f96f9d4de2 | 604 | if (kENET_MiiSpeed10M == speed) |
<> | 154:37f96f9d4de2 | 605 | { |
<> | 154:37f96f9d4de2 | 606 | rcr |= ENET_RCR_RMII_10T_MASK; |
<> | 154:37f96f9d4de2 | 607 | } |
<> | 154:37f96f9d4de2 | 608 | else |
<> | 154:37f96f9d4de2 | 609 | { |
<> | 154:37f96f9d4de2 | 610 | rcr &= ~ENET_RCR_RMII_10T_MASK; |
<> | 154:37f96f9d4de2 | 611 | } |
<> | 154:37f96f9d4de2 | 612 | /* Set duplex mode. */ |
<> | 154:37f96f9d4de2 | 613 | if (duplex == kENET_MiiHalfDuplex) |
<> | 154:37f96f9d4de2 | 614 | { |
<> | 154:37f96f9d4de2 | 615 | rcr |= ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 616 | tcr &= ~ENET_TCR_FDEN_MASK; |
<> | 154:37f96f9d4de2 | 617 | } |
<> | 154:37f96f9d4de2 | 618 | else |
<> | 154:37f96f9d4de2 | 619 | { |
<> | 154:37f96f9d4de2 | 620 | rcr &= ~ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 621 | tcr |= ENET_TCR_FDEN_MASK; |
<> | 154:37f96f9d4de2 | 622 | } |
<> | 154:37f96f9d4de2 | 623 | |
<> | 154:37f96f9d4de2 | 624 | base->RCR = rcr; |
<> | 154:37f96f9d4de2 | 625 | base->TCR = tcr; |
<> | 154:37f96f9d4de2 | 626 | } |
<> | 154:37f96f9d4de2 | 627 | |
<> | 154:37f96f9d4de2 | 628 | void ENET_SetMacAddr(ENET_Type *base, uint8_t *macAddr) |
<> | 154:37f96f9d4de2 | 629 | { |
<> | 154:37f96f9d4de2 | 630 | uint32_t address; |
<> | 154:37f96f9d4de2 | 631 | |
<> | 154:37f96f9d4de2 | 632 | /* Set physical address lower register. */ |
<> | 154:37f96f9d4de2 | 633 | address = (uint32_t)(((uint32_t)macAddr[0] << 24U) | ((uint32_t)macAddr[1] << 16U) | ((uint32_t)macAddr[2] << 8U) | |
<> | 154:37f96f9d4de2 | 634 | (uint32_t)macAddr[3]); |
<> | 154:37f96f9d4de2 | 635 | base->PALR = address; |
<> | 154:37f96f9d4de2 | 636 | /* Set physical address high register. */ |
<> | 154:37f96f9d4de2 | 637 | address = (uint32_t)(((uint32_t)macAddr[4] << 8U) | ((uint32_t)macAddr[5])); |
<> | 154:37f96f9d4de2 | 638 | base->PAUR = address << ENET_PAUR_PADDR2_SHIFT; |
<> | 154:37f96f9d4de2 | 639 | } |
<> | 154:37f96f9d4de2 | 640 | |
<> | 154:37f96f9d4de2 | 641 | void ENET_GetMacAddr(ENET_Type *base, uint8_t *macAddr) |
<> | 154:37f96f9d4de2 | 642 | { |
<> | 154:37f96f9d4de2 | 643 | assert(macAddr); |
<> | 154:37f96f9d4de2 | 644 | |
<> | 154:37f96f9d4de2 | 645 | uint32_t address; |
<> | 154:37f96f9d4de2 | 646 | |
<> | 154:37f96f9d4de2 | 647 | /* Get from physical address lower register. */ |
<> | 154:37f96f9d4de2 | 648 | address = base->PALR; |
<> | 154:37f96f9d4de2 | 649 | macAddr[0] = 0xFFU & (address >> 24U); |
<> | 154:37f96f9d4de2 | 650 | macAddr[1] = 0xFFU & (address >> 16U); |
<> | 154:37f96f9d4de2 | 651 | macAddr[2] = 0xFFU & (address >> 8U); |
<> | 154:37f96f9d4de2 | 652 | macAddr[3] = 0xFFU & address; |
<> | 154:37f96f9d4de2 | 653 | |
<> | 154:37f96f9d4de2 | 654 | /* Get from physical address high register. */ |
<> | 154:37f96f9d4de2 | 655 | address = (base->PAUR & ENET_PAUR_PADDR2_MASK) >> ENET_PAUR_PADDR2_SHIFT; |
<> | 154:37f96f9d4de2 | 656 | macAddr[4] = 0xFFU & (address >> 8U); |
<> | 154:37f96f9d4de2 | 657 | macAddr[5] = 0xFFU & address; |
<> | 154:37f96f9d4de2 | 658 | } |
<> | 154:37f96f9d4de2 | 659 | |
<> | 154:37f96f9d4de2 | 660 | void ENET_SetSMI(ENET_Type *base, uint32_t srcClock_Hz, bool isPreambleDisabled) |
<> | 154:37f96f9d4de2 | 661 | { |
<> | 154:37f96f9d4de2 | 662 | assert(srcClock_Hz); |
<> | 154:37f96f9d4de2 | 663 | |
<> | 154:37f96f9d4de2 | 664 | uint32_t clkCycle = 0; |
<> | 154:37f96f9d4de2 | 665 | uint32_t speed = 0; |
<> | 154:37f96f9d4de2 | 666 | uint32_t mscr = 0; |
<> | 154:37f96f9d4de2 | 667 | |
<> | 154:37f96f9d4de2 | 668 | /* Calculate the MII speed which controls the frequency of the MDC. */ |
<> | 154:37f96f9d4de2 | 669 | speed = srcClock_Hz / (2 * ENET_MDC_FREQUENCY); |
<> | 154:37f96f9d4de2 | 670 | /* Calculate the hold time on the MDIO output. */ |
<> | 154:37f96f9d4de2 | 671 | clkCycle = (10 + ENET_NANOSECOND_ONE_SECOND / srcClock_Hz - 1) / (ENET_NANOSECOND_ONE_SECOND / srcClock_Hz) - 1; |
<> | 154:37f96f9d4de2 | 672 | /* Build the configuration for MDC/MDIO control. */ |
<> | 154:37f96f9d4de2 | 673 | mscr = ENET_MSCR_MII_SPEED(speed) | ENET_MSCR_DIS_PRE(isPreambleDisabled) | ENET_MSCR_HOLDTIME(clkCycle); |
<> | 154:37f96f9d4de2 | 674 | base->MSCR = mscr; |
<> | 154:37f96f9d4de2 | 675 | } |
<> | 154:37f96f9d4de2 | 676 | |
<> | 154:37f96f9d4de2 | 677 | void ENET_StartSMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_write_t operation, uint32_t data) |
<> | 154:37f96f9d4de2 | 678 | { |
<> | 154:37f96f9d4de2 | 679 | uint32_t mmfr = 0; |
<> | 154:37f96f9d4de2 | 680 | |
<> | 154:37f96f9d4de2 | 681 | /* Build MII write command. */ |
<> | 154:37f96f9d4de2 | 682 | mmfr = ENET_MMFR_ST(1) | ENET_MMFR_OP(operation) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(phyReg) | ENET_MMFR_TA(2) | |
<> | 154:37f96f9d4de2 | 683 | (data & 0xFFFF); |
<> | 154:37f96f9d4de2 | 684 | base->MMFR = mmfr; |
<> | 154:37f96f9d4de2 | 685 | } |
<> | 154:37f96f9d4de2 | 686 | |
<> | 154:37f96f9d4de2 | 687 | void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_read_t operation) |
<> | 154:37f96f9d4de2 | 688 | { |
<> | 154:37f96f9d4de2 | 689 | uint32_t mmfr = 0; |
<> | 154:37f96f9d4de2 | 690 | |
<> | 154:37f96f9d4de2 | 691 | /* Build MII read command. */ |
<> | 154:37f96f9d4de2 | 692 | mmfr = ENET_MMFR_ST(1) | ENET_MMFR_OP(operation) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(phyReg) | ENET_MMFR_TA(2); |
<> | 154:37f96f9d4de2 | 693 | base->MMFR = mmfr; |
<> | 154:37f96f9d4de2 | 694 | } |
<> | 154:37f96f9d4de2 | 695 | |
<> | 154:37f96f9d4de2 | 696 | void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) |
<> | 154:37f96f9d4de2 | 697 | { |
<> | 154:37f96f9d4de2 | 698 | assert(handle); |
<> | 154:37f96f9d4de2 | 699 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 700 | assert(eErrorStatic); |
<> | 154:37f96f9d4de2 | 701 | |
<> | 154:37f96f9d4de2 | 702 | uint16_t control = 0; |
<> | 154:37f96f9d4de2 | 703 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 704 | |
<> | 154:37f96f9d4de2 | 705 | do |
<> | 154:37f96f9d4de2 | 706 | { |
<> | 154:37f96f9d4de2 | 707 | /* The last buffer descriptor of a frame. */ |
<> | 154:37f96f9d4de2 | 708 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 709 | { |
<> | 154:37f96f9d4de2 | 710 | control = curBuffDescrip->control; |
<> | 154:37f96f9d4de2 | 711 | if (control & ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK) |
<> | 154:37f96f9d4de2 | 712 | { |
<> | 154:37f96f9d4de2 | 713 | /* The receive truncate error. */ |
<> | 154:37f96f9d4de2 | 714 | eErrorStatic->statsRxTruncateErr++; |
<> | 154:37f96f9d4de2 | 715 | } |
<> | 154:37f96f9d4de2 | 716 | if (control & ENET_BUFFDESCRIPTOR_RX_OVERRUN_MASK) |
<> | 154:37f96f9d4de2 | 717 | { |
<> | 154:37f96f9d4de2 | 718 | /* The receive over run error. */ |
<> | 154:37f96f9d4de2 | 719 | eErrorStatic->statsRxOverRunErr++; |
<> | 154:37f96f9d4de2 | 720 | } |
<> | 154:37f96f9d4de2 | 721 | if (control & ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK) |
<> | 154:37f96f9d4de2 | 722 | { |
<> | 154:37f96f9d4de2 | 723 | /* The receive length violation error. */ |
<> | 154:37f96f9d4de2 | 724 | eErrorStatic->statsRxLenGreaterErr++; |
<> | 154:37f96f9d4de2 | 725 | } |
<> | 154:37f96f9d4de2 | 726 | if (control & ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK) |
<> | 154:37f96f9d4de2 | 727 | { |
<> | 154:37f96f9d4de2 | 728 | /* The receive alignment error. */ |
<> | 154:37f96f9d4de2 | 729 | eErrorStatic->statsRxAlignErr++; |
<> | 154:37f96f9d4de2 | 730 | } |
<> | 154:37f96f9d4de2 | 731 | if (control & ENET_BUFFDESCRIPTOR_RX_CRC_MASK) |
<> | 154:37f96f9d4de2 | 732 | { |
<> | 154:37f96f9d4de2 | 733 | /* The receive CRC error. */ |
<> | 154:37f96f9d4de2 | 734 | eErrorStatic->statsRxFcsErr++; |
<> | 154:37f96f9d4de2 | 735 | } |
<> | 154:37f96f9d4de2 | 736 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 737 | uint16_t controlExt = curBuffDescrip->controlExtend1; |
<> | 154:37f96f9d4de2 | 738 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_MACERR_MASK) |
<> | 154:37f96f9d4de2 | 739 | { |
<> | 154:37f96f9d4de2 | 740 | /* The MAC error. */ |
<> | 154:37f96f9d4de2 | 741 | eErrorStatic->statsRxMacErr++; |
<> | 154:37f96f9d4de2 | 742 | } |
<> | 154:37f96f9d4de2 | 743 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_PHYERR_MASK) |
<> | 154:37f96f9d4de2 | 744 | { |
<> | 154:37f96f9d4de2 | 745 | /* The PHY error. */ |
<> | 154:37f96f9d4de2 | 746 | eErrorStatic->statsRxPhyErr++; |
<> | 154:37f96f9d4de2 | 747 | } |
<> | 154:37f96f9d4de2 | 748 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_COLLISION_MASK) |
<> | 154:37f96f9d4de2 | 749 | { |
<> | 154:37f96f9d4de2 | 750 | /* The receive collision error. */ |
<> | 154:37f96f9d4de2 | 751 | eErrorStatic->statsRxCollisionErr++; |
<> | 154:37f96f9d4de2 | 752 | } |
<> | 154:37f96f9d4de2 | 753 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 754 | |
<> | 154:37f96f9d4de2 | 755 | break; |
<> | 154:37f96f9d4de2 | 756 | } |
<> | 154:37f96f9d4de2 | 757 | |
<> | 154:37f96f9d4de2 | 758 | /* Increase the buffer descriptor, if it is the last one, increase to first one of the ring buffer. */ |
<> | 154:37f96f9d4de2 | 759 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 760 | { |
<> | 154:37f96f9d4de2 | 761 | curBuffDescrip = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 762 | } |
<> | 154:37f96f9d4de2 | 763 | else |
<> | 154:37f96f9d4de2 | 764 | { |
<> | 154:37f96f9d4de2 | 765 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 766 | } |
<> | 154:37f96f9d4de2 | 767 | |
<> | 154:37f96f9d4de2 | 768 | } while (curBuffDescrip != handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 769 | } |
<> | 154:37f96f9d4de2 | 770 | |
<> | 154:37f96f9d4de2 | 771 | status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) |
<> | 154:37f96f9d4de2 | 772 | { |
<> | 154:37f96f9d4de2 | 773 | assert(handle); |
<> | 154:37f96f9d4de2 | 774 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 775 | assert(length); |
<> | 154:37f96f9d4de2 | 776 | |
<> | 154:37f96f9d4de2 | 777 | /* Reset the length to zero. */ |
<> | 154:37f96f9d4de2 | 778 | *length = 0; |
<> | 154:37f96f9d4de2 | 779 | |
<> | 154:37f96f9d4de2 | 780 | uint16_t validLastMask = ENET_BUFFDESCRIPTOR_RX_LAST_MASK | ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 781 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 782 | |
<> | 154:37f96f9d4de2 | 783 | /* Check the current buffer descriptor's empty flag. if empty means there is no frame received. */ |
<> | 154:37f96f9d4de2 | 784 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) |
<> | 154:37f96f9d4de2 | 785 | { |
<> | 154:37f96f9d4de2 | 786 | return kStatus_ENET_RxFrameEmpty; |
<> | 154:37f96f9d4de2 | 787 | } |
<> | 154:37f96f9d4de2 | 788 | |
<> | 154:37f96f9d4de2 | 789 | do |
<> | 154:37f96f9d4de2 | 790 | { |
<> | 154:37f96f9d4de2 | 791 | /* Find the last buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 792 | if ((curBuffDescrip->control & validLastMask) == ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 793 | { |
<> | 154:37f96f9d4de2 | 794 | /* The last buffer descriptor in the frame check the status of the received frame. */ |
<> | 154:37f96f9d4de2 | 795 | if ((curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_ERR_MASK) |
<> | 154:37f96f9d4de2 | 796 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 797 | || (curBuffDescrip->controlExtend1 & ENET_BUFFDESCRIPTOR_RX_EXT_ERR_MASK) |
<> | 154:37f96f9d4de2 | 798 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 799 | ) |
<> | 154:37f96f9d4de2 | 800 | { |
<> | 154:37f96f9d4de2 | 801 | return kStatus_ENET_RxFrameError; |
<> | 154:37f96f9d4de2 | 802 | } |
<> | 154:37f96f9d4de2 | 803 | /* FCS is removed by MAC. */ |
<> | 154:37f96f9d4de2 | 804 | *length = curBuffDescrip->length; |
<> | 154:37f96f9d4de2 | 805 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 806 | } |
<> | 154:37f96f9d4de2 | 807 | /* Increase the buffer descriptor, if it is the last one, increase to first one of the ring buffer. */ |
<> | 154:37f96f9d4de2 | 808 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 809 | { |
<> | 154:37f96f9d4de2 | 810 | curBuffDescrip = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 811 | } |
<> | 154:37f96f9d4de2 | 812 | else |
<> | 154:37f96f9d4de2 | 813 | { |
<> | 154:37f96f9d4de2 | 814 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 815 | } |
<> | 154:37f96f9d4de2 | 816 | |
<> | 154:37f96f9d4de2 | 817 | } while (curBuffDescrip != handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 818 | |
<> | 154:37f96f9d4de2 | 819 | /* The frame is on processing - set to empty status to make application to receive it next time. */ |
<> | 154:37f96f9d4de2 | 820 | return kStatus_ENET_RxFrameEmpty; |
<> | 154:37f96f9d4de2 | 821 | } |
<> | 154:37f96f9d4de2 | 822 | |
<> | 154:37f96f9d4de2 | 823 | status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) |
<> | 154:37f96f9d4de2 | 824 | { |
<> | 154:37f96f9d4de2 | 825 | assert(handle); |
<> | 154:37f96f9d4de2 | 826 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 827 | |
<> | 154:37f96f9d4de2 | 828 | uint32_t len = 0; |
<> | 154:37f96f9d4de2 | 829 | uint32_t offset = 0; |
<> | 154:37f96f9d4de2 | 830 | uint16_t control; |
<> | 154:37f96f9d4de2 | 831 | bool isLastBuff = false; |
<> | 154:37f96f9d4de2 | 832 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 833 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 834 | |
<> | 154:37f96f9d4de2 | 835 | /* For data-NULL input, only update the buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 836 | if (!data) |
<> | 154:37f96f9d4de2 | 837 | { |
<> | 154:37f96f9d4de2 | 838 | do |
<> | 154:37f96f9d4de2 | 839 | { |
<> | 154:37f96f9d4de2 | 840 | /* Update the control flag. */ |
<> | 154:37f96f9d4de2 | 841 | control = handle->rxBdCurrent->control; |
<> | 154:37f96f9d4de2 | 842 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 843 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 844 | |
<> | 154:37f96f9d4de2 | 845 | /* Find the last buffer descriptor for the frame. */ |
<> | 154:37f96f9d4de2 | 846 | if (control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 847 | { |
<> | 154:37f96f9d4de2 | 848 | break; |
<> | 154:37f96f9d4de2 | 849 | } |
<> | 154:37f96f9d4de2 | 850 | |
<> | 154:37f96f9d4de2 | 851 | } while (handle->rxBdCurrent != curBuffDescrip); |
<> | 154:37f96f9d4de2 | 852 | |
<> | 154:37f96f9d4de2 | 853 | return result; |
<> | 154:37f96f9d4de2 | 854 | } |
<> | 154:37f96f9d4de2 | 855 | else |
<> | 154:37f96f9d4de2 | 856 | { |
<> | 154:37f96f9d4de2 | 857 | /* A frame on one buffer or several receive buffers are both considered. */ |
<> | 154:37f96f9d4de2 | 858 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 859 | enet_ptp_time_data_t ptpTimestamp; |
<> | 154:37f96f9d4de2 | 860 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 861 | |
<> | 154:37f96f9d4de2 | 862 | /* Parse the PTP message according to the header message. */ |
<> | 154:37f96f9d4de2 | 863 | isPtpEventMessage = ENET_Ptp1588ParseFrame(curBuffDescrip->buffer, &ptpTimestamp, false); |
<> | 154:37f96f9d4de2 | 864 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 865 | |
<> | 154:37f96f9d4de2 | 866 | while (!isLastBuff) |
<> | 154:37f96f9d4de2 | 867 | { |
<> | 154:37f96f9d4de2 | 868 | /* The last buffer descriptor of a frame. */ |
<> | 154:37f96f9d4de2 | 869 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 870 | { |
<> | 154:37f96f9d4de2 | 871 | /* This is a valid frame. */ |
<> | 154:37f96f9d4de2 | 872 | isLastBuff = true; |
<> | 154:37f96f9d4de2 | 873 | if (length == curBuffDescrip->length) |
<> | 154:37f96f9d4de2 | 874 | { |
<> | 154:37f96f9d4de2 | 875 | /* Copy the frame to user's buffer without FCS. */ |
<> | 154:37f96f9d4de2 | 876 | len = curBuffDescrip->length - offset; |
<> | 154:37f96f9d4de2 | 877 | memcpy(data + offset, curBuffDescrip->buffer, len); |
<> | 154:37f96f9d4de2 | 878 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 879 | /* Store the PTP 1588 timestamp for received PTP event frame. */ |
<> | 154:37f96f9d4de2 | 880 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 881 | { |
<> | 154:37f96f9d4de2 | 882 | /* Set the timestamp to the timestamp ring. */ |
<> | 154:37f96f9d4de2 | 883 | ptpTimestamp.timeStamp.nanosecond = curBuffDescrip->timestamp; |
<> | 154:37f96f9d4de2 | 884 | result = ENET_StoreRxFrameTime(base, handle, &ptpTimestamp); |
<> | 154:37f96f9d4de2 | 885 | } |
<> | 154:37f96f9d4de2 | 886 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 887 | |
<> | 154:37f96f9d4de2 | 888 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 889 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 890 | return result; |
<> | 154:37f96f9d4de2 | 891 | } |
<> | 154:37f96f9d4de2 | 892 | else |
<> | 154:37f96f9d4de2 | 893 | { |
<> | 154:37f96f9d4de2 | 894 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 895 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 896 | } |
<> | 154:37f96f9d4de2 | 897 | } |
<> | 154:37f96f9d4de2 | 898 | else |
<> | 154:37f96f9d4de2 | 899 | { |
<> | 154:37f96f9d4de2 | 900 | /* Store a frame on several buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 901 | isLastBuff = false; |
<> | 154:37f96f9d4de2 | 902 | /* Length check. */ |
<> | 154:37f96f9d4de2 | 903 | if (offset >= length) |
<> | 154:37f96f9d4de2 | 904 | { |
<> | 154:37f96f9d4de2 | 905 | break; |
<> | 154:37f96f9d4de2 | 906 | } |
<> | 154:37f96f9d4de2 | 907 | memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); |
<> | 154:37f96f9d4de2 | 908 | offset += handle->rxBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 909 | |
<> | 154:37f96f9d4de2 | 910 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 911 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 912 | } |
<> | 154:37f96f9d4de2 | 913 | |
<> | 154:37f96f9d4de2 | 914 | /* Get the current buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 915 | curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 916 | } |
<> | 154:37f96f9d4de2 | 917 | } |
<> | 154:37f96f9d4de2 | 918 | |
<> | 154:37f96f9d4de2 | 919 | return kStatus_ENET_RxFrameFail; |
<> | 154:37f96f9d4de2 | 920 | } |
<> | 154:37f96f9d4de2 | 921 | |
<> | 154:37f96f9d4de2 | 922 | static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 923 | { |
<> | 154:37f96f9d4de2 | 924 | assert(handle); |
<> | 154:37f96f9d4de2 | 925 | |
<> | 154:37f96f9d4de2 | 926 | /* Clears status. */ |
<> | 154:37f96f9d4de2 | 927 | handle->rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 928 | /* Sets the receive buffer descriptor with the empty flag. */ |
<> | 154:37f96f9d4de2 | 929 | handle->rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 930 | |
<> | 154:37f96f9d4de2 | 931 | /* Increase current buffer descriptor to the next one. */ |
<> | 154:37f96f9d4de2 | 932 | if (handle->rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 933 | { |
<> | 154:37f96f9d4de2 | 934 | handle->rxBdCurrent = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 935 | } |
<> | 154:37f96f9d4de2 | 936 | else |
<> | 154:37f96f9d4de2 | 937 | { |
<> | 154:37f96f9d4de2 | 938 | handle->rxBdCurrent++; |
<> | 154:37f96f9d4de2 | 939 | } |
<> | 154:37f96f9d4de2 | 940 | |
<> | 154:37f96f9d4de2 | 941 | /* Actives the receive buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 942 | base->RDAR = ENET_RDAR_RDAR_MASK; |
<> | 154:37f96f9d4de2 | 943 | } |
<> | 154:37f96f9d4de2 | 944 | |
<> | 154:37f96f9d4de2 | 945 | status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) |
<> | 154:37f96f9d4de2 | 946 | { |
<> | 154:37f96f9d4de2 | 947 | assert(handle); |
<> | 154:37f96f9d4de2 | 948 | assert(handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 949 | assert(data); |
<> | 154:37f96f9d4de2 | 950 | assert(length <= (ENET_FRAME_MAX_VALNFRAMELEN - 4)); |
<> | 154:37f96f9d4de2 | 951 | |
<> | 154:37f96f9d4de2 | 952 | volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdCurrent; |
<> | 154:37f96f9d4de2 | 953 | uint32_t len = 0; |
<> | 154:37f96f9d4de2 | 954 | uint32_t sizeleft = 0; |
<> | 154:37f96f9d4de2 | 955 | |
<> | 154:37f96f9d4de2 | 956 | /* Check if the transmit buffer is ready. */ |
<> | 154:37f96f9d4de2 | 957 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 958 | { |
<> | 154:37f96f9d4de2 | 959 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 960 | } |
<> | 154:37f96f9d4de2 | 961 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 962 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 963 | /* Check PTP message with the PTP header. */ |
<> | 154:37f96f9d4de2 | 964 | isPtpEventMessage = ENET_Ptp1588ParseFrame(data, NULL, true); |
<> | 154:37f96f9d4de2 | 965 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 966 | /* One transmit buffer is enough for one frame. */ |
<> | 154:37f96f9d4de2 | 967 | if (handle->txBuffSizeAlign >= length) |
<> | 154:37f96f9d4de2 | 968 | { |
<> | 154:37f96f9d4de2 | 969 | /* Copy data to the buffer for uDMA transfer. */ |
<> | 154:37f96f9d4de2 | 970 | memcpy(curBuffDescrip->buffer, data, length); |
<> | 154:37f96f9d4de2 | 971 | /* Set data length. */ |
<> | 154:37f96f9d4de2 | 972 | curBuffDescrip->length = length; |
<> | 154:37f96f9d4de2 | 973 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 974 | /* For enable the timestamp. */ |
<> | 154:37f96f9d4de2 | 975 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 976 | { |
<> | 154:37f96f9d4de2 | 977 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 978 | } |
<> | 154:37f96f9d4de2 | 979 | else |
<> | 154:37f96f9d4de2 | 980 | { |
<> | 154:37f96f9d4de2 | 981 | curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 982 | } |
<> | 154:37f96f9d4de2 | 983 | |
<> | 154:37f96f9d4de2 | 984 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 985 | curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); |
<> | 154:37f96f9d4de2 | 986 | |
<> | 154:37f96f9d4de2 | 987 | /* Increase the buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 988 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 989 | { |
<> | 154:37f96f9d4de2 | 990 | handle->txBdCurrent = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 991 | } |
<> | 154:37f96f9d4de2 | 992 | else |
<> | 154:37f96f9d4de2 | 993 | { |
<> | 154:37f96f9d4de2 | 994 | handle->txBdCurrent++; |
<> | 154:37f96f9d4de2 | 995 | } |
<> | 154:37f96f9d4de2 | 996 | |
<> | 154:37f96f9d4de2 | 997 | /* Active the transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 998 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 999 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1000 | } |
<> | 154:37f96f9d4de2 | 1001 | else |
<> | 154:37f96f9d4de2 | 1002 | { |
<> | 154:37f96f9d4de2 | 1003 | /* One frame requires more than one transmit buffers. */ |
<> | 154:37f96f9d4de2 | 1004 | do |
<> | 154:37f96f9d4de2 | 1005 | { |
<> | 154:37f96f9d4de2 | 1006 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1007 | /* For enable the timestamp. */ |
<> | 154:37f96f9d4de2 | 1008 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 1009 | { |
<> | 154:37f96f9d4de2 | 1010 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 1011 | } |
<> | 154:37f96f9d4de2 | 1012 | else |
<> | 154:37f96f9d4de2 | 1013 | { |
<> | 154:37f96f9d4de2 | 1014 | curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 1015 | } |
<> | 154:37f96f9d4de2 | 1016 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1017 | |
<> | 154:37f96f9d4de2 | 1018 | /* Increase the buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 1019 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1020 | { |
<> | 154:37f96f9d4de2 | 1021 | handle->txBdCurrent = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1022 | } |
<> | 154:37f96f9d4de2 | 1023 | else |
<> | 154:37f96f9d4de2 | 1024 | { |
<> | 154:37f96f9d4de2 | 1025 | handle->txBdCurrent++; |
<> | 154:37f96f9d4de2 | 1026 | } |
<> | 154:37f96f9d4de2 | 1027 | /* update the size left to be transmit. */ |
<> | 154:37f96f9d4de2 | 1028 | sizeleft = length - len; |
<> | 154:37f96f9d4de2 | 1029 | if (sizeleft > handle->txBuffSizeAlign) |
<> | 154:37f96f9d4de2 | 1030 | { |
<> | 154:37f96f9d4de2 | 1031 | /* Data copy. */ |
<> | 154:37f96f9d4de2 | 1032 | memcpy(curBuffDescrip->buffer, data + len, handle->txBuffSizeAlign); |
<> | 154:37f96f9d4de2 | 1033 | /* Data length update. */ |
<> | 154:37f96f9d4de2 | 1034 | curBuffDescrip->length = handle->txBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 1035 | len += handle->txBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 1036 | /* Sets the control flag. */ |
<> | 154:37f96f9d4de2 | 1037 | curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; |
<> | 154:37f96f9d4de2 | 1038 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; |
<> | 154:37f96f9d4de2 | 1039 | /* Active the transmit buffer descriptor*/ |
<> | 154:37f96f9d4de2 | 1040 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 1041 | } |
<> | 154:37f96f9d4de2 | 1042 | else |
<> | 154:37f96f9d4de2 | 1043 | { |
<> | 154:37f96f9d4de2 | 1044 | memcpy(curBuffDescrip->buffer, data + len, sizeleft); |
<> | 154:37f96f9d4de2 | 1045 | curBuffDescrip->length = sizeleft; |
<> | 154:37f96f9d4de2 | 1046 | /* Set Last buffer wrap flag. */ |
<> | 154:37f96f9d4de2 | 1047 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK; |
<> | 154:37f96f9d4de2 | 1048 | /* Active the transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1049 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 1050 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1051 | } |
<> | 154:37f96f9d4de2 | 1052 | |
<> | 154:37f96f9d4de2 | 1053 | /* Get the current buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 1054 | curBuffDescrip = handle->txBdCurrent; |
<> | 154:37f96f9d4de2 | 1055 | |
<> | 154:37f96f9d4de2 | 1056 | } while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); |
<> | 154:37f96f9d4de2 | 1057 | |
<> | 154:37f96f9d4de2 | 1058 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1059 | } |
<> | 154:37f96f9d4de2 | 1060 | } |
<> | 154:37f96f9d4de2 | 1061 | |
<> | 154:37f96f9d4de2 | 1062 | void ENET_AddMulticastGroup(ENET_Type *base, uint8_t *address) |
<> | 154:37f96f9d4de2 | 1063 | { |
<> | 154:37f96f9d4de2 | 1064 | assert(address); |
<> | 154:37f96f9d4de2 | 1065 | |
<> | 154:37f96f9d4de2 | 1066 | uint32_t crc = 0xFFFFFFFFU; |
<> | 154:37f96f9d4de2 | 1067 | uint32_t count1 = 0; |
<> | 154:37f96f9d4de2 | 1068 | uint32_t count2 = 0; |
<> | 154:37f96f9d4de2 | 1069 | |
<> | 154:37f96f9d4de2 | 1070 | /* Calculates the CRC-32 polynomial on the multicast group address. */ |
<> | 154:37f96f9d4de2 | 1071 | for (count1 = 0; count1 < ENET_FRAME_MACLEN; count1++) |
<> | 154:37f96f9d4de2 | 1072 | { |
<> | 154:37f96f9d4de2 | 1073 | uint8_t c = address[count1]; |
<> | 154:37f96f9d4de2 | 1074 | for (count2 = 0; count2 < 0x08U; count2++) |
<> | 154:37f96f9d4de2 | 1075 | { |
<> | 154:37f96f9d4de2 | 1076 | if ((c ^ crc) & 1U) |
<> | 154:37f96f9d4de2 | 1077 | { |
<> | 154:37f96f9d4de2 | 1078 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1079 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1080 | crc ^= 0xEDB88320U; |
<> | 154:37f96f9d4de2 | 1081 | } |
<> | 154:37f96f9d4de2 | 1082 | else |
<> | 154:37f96f9d4de2 | 1083 | { |
<> | 154:37f96f9d4de2 | 1084 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1085 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1086 | } |
<> | 154:37f96f9d4de2 | 1087 | } |
<> | 154:37f96f9d4de2 | 1088 | } |
<> | 154:37f96f9d4de2 | 1089 | |
<> | 154:37f96f9d4de2 | 1090 | /* Enable a multicast group address. */ |
<> | 154:37f96f9d4de2 | 1091 | if (!((crc >> 0x1FU) & 1U)) |
<> | 154:37f96f9d4de2 | 1092 | { |
<> | 154:37f96f9d4de2 | 1093 | base->GALR |= 1U << ((crc >> 0x1AU) & 0x1FU); |
<> | 154:37f96f9d4de2 | 1094 | } |
<> | 154:37f96f9d4de2 | 1095 | else |
<> | 154:37f96f9d4de2 | 1096 | { |
<> | 154:37f96f9d4de2 | 1097 | base->GAUR |= 1U << ((crc >> 0x1AU) & 0x1FU); |
<> | 154:37f96f9d4de2 | 1098 | } |
<> | 154:37f96f9d4de2 | 1099 | } |
<> | 154:37f96f9d4de2 | 1100 | |
<> | 154:37f96f9d4de2 | 1101 | void ENET_LeaveMulticastGroup(ENET_Type *base, uint8_t *address) |
<> | 154:37f96f9d4de2 | 1102 | { |
<> | 154:37f96f9d4de2 | 1103 | assert(address); |
<> | 154:37f96f9d4de2 | 1104 | |
<> | 154:37f96f9d4de2 | 1105 | uint32_t crc = 0xFFFFFFFFU; |
<> | 154:37f96f9d4de2 | 1106 | uint32_t count1 = 0; |
<> | 154:37f96f9d4de2 | 1107 | uint32_t count2 = 0; |
<> | 154:37f96f9d4de2 | 1108 | |
<> | 154:37f96f9d4de2 | 1109 | /* Calculates the CRC-32 polynomial on the multicast group address. */ |
<> | 154:37f96f9d4de2 | 1110 | for (count1 = 0; count1 < ENET_FRAME_MACLEN; count1++) |
<> | 154:37f96f9d4de2 | 1111 | { |
<> | 154:37f96f9d4de2 | 1112 | uint8_t c = address[count1]; |
<> | 154:37f96f9d4de2 | 1113 | for (count2 = 0; count2 < 0x08U; count2++) |
<> | 154:37f96f9d4de2 | 1114 | { |
<> | 154:37f96f9d4de2 | 1115 | if ((c ^ crc) & 1U) |
<> | 154:37f96f9d4de2 | 1116 | { |
<> | 154:37f96f9d4de2 | 1117 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1118 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1119 | crc ^= 0xEDB88320U; |
<> | 154:37f96f9d4de2 | 1120 | } |
<> | 154:37f96f9d4de2 | 1121 | else |
<> | 154:37f96f9d4de2 | 1122 | { |
<> | 154:37f96f9d4de2 | 1123 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1124 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1125 | } |
<> | 154:37f96f9d4de2 | 1126 | } |
<> | 154:37f96f9d4de2 | 1127 | } |
<> | 154:37f96f9d4de2 | 1128 | |
<> | 154:37f96f9d4de2 | 1129 | /* Set the hash table. */ |
<> | 154:37f96f9d4de2 | 1130 | if (!((crc >> 0x1FU) & 1U)) |
<> | 154:37f96f9d4de2 | 1131 | { |
<> | 154:37f96f9d4de2 | 1132 | base->GALR &= ~(1U << ((crc >> 0x1AU) & 0x1FU)); |
<> | 154:37f96f9d4de2 | 1133 | } |
<> | 154:37f96f9d4de2 | 1134 | else |
<> | 154:37f96f9d4de2 | 1135 | { |
<> | 154:37f96f9d4de2 | 1136 | base->GAUR &= ~(1U << ((crc >> 0x1AU) & 0x1FU)); |
<> | 154:37f96f9d4de2 | 1137 | } |
<> | 154:37f96f9d4de2 | 1138 | } |
<> | 154:37f96f9d4de2 | 1139 | |
<> | 154:37f96f9d4de2 | 1140 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1141 | status_t ENET_GetTxErrAfterSendFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) |
<> | 154:37f96f9d4de2 | 1142 | { |
<> | 154:37f96f9d4de2 | 1143 | assert(handle); |
<> | 154:37f96f9d4de2 | 1144 | assert(eErrorStatic); |
<> | 154:37f96f9d4de2 | 1145 | |
<> | 154:37f96f9d4de2 | 1146 | uint16_t control = 0; |
<> | 154:37f96f9d4de2 | 1147 | uint16_t controlExt = 0; |
<> | 154:37f96f9d4de2 | 1148 | |
<> | 154:37f96f9d4de2 | 1149 | do |
<> | 154:37f96f9d4de2 | 1150 | { |
<> | 154:37f96f9d4de2 | 1151 | /* Get the current dirty transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1152 | control = handle->txBdDirtyStatic->control; |
<> | 154:37f96f9d4de2 | 1153 | controlExt = handle->txBdDirtyStatic->controlExtend0; |
<> | 154:37f96f9d4de2 | 1154 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1155 | if (control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1156 | { |
<> | 154:37f96f9d4de2 | 1157 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1158 | } |
<> | 154:37f96f9d4de2 | 1159 | /* Increase the transmit dirty static pointer. */ |
<> | 154:37f96f9d4de2 | 1160 | if (handle->txBdDirtyStatic->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1161 | { |
<> | 154:37f96f9d4de2 | 1162 | handle->txBdDirtyStatic = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1163 | } |
<> | 154:37f96f9d4de2 | 1164 | else |
<> | 154:37f96f9d4de2 | 1165 | { |
<> | 154:37f96f9d4de2 | 1166 | handle->txBdDirtyStatic++; |
<> | 154:37f96f9d4de2 | 1167 | } |
<> | 154:37f96f9d4de2 | 1168 | |
<> | 154:37f96f9d4de2 | 1169 | /* If the transmit buffer descriptor is ready and the last buffer descriptor, store packet statistic. */ |
<> | 154:37f96f9d4de2 | 1170 | if (control & ENET_BUFFDESCRIPTOR_TX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 1171 | { |
<> | 154:37f96f9d4de2 | 1172 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_ERR_MASK) |
<> | 154:37f96f9d4de2 | 1173 | { |
<> | 154:37f96f9d4de2 | 1174 | /* Transmit error. */ |
<> | 154:37f96f9d4de2 | 1175 | eErrorStatic->statsTxErr++; |
<> | 154:37f96f9d4de2 | 1176 | } |
<> | 154:37f96f9d4de2 | 1177 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_EXCCOLLISIONERR_MASK) |
<> | 154:37f96f9d4de2 | 1178 | { |
<> | 154:37f96f9d4de2 | 1179 | /* Transmit excess collision error. */ |
<> | 154:37f96f9d4de2 | 1180 | eErrorStatic->statsTxExcessCollisionErr++; |
<> | 154:37f96f9d4de2 | 1181 | } |
<> | 154:37f96f9d4de2 | 1182 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_LATECOLLISIONERR_MASK) |
<> | 154:37f96f9d4de2 | 1183 | { |
<> | 154:37f96f9d4de2 | 1184 | /* Transmit late collision error. */ |
<> | 154:37f96f9d4de2 | 1185 | eErrorStatic->statsTxLateCollisionErr++; |
<> | 154:37f96f9d4de2 | 1186 | } |
<> | 154:37f96f9d4de2 | 1187 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_UNDERFLOWERR_MASK) |
<> | 154:37f96f9d4de2 | 1188 | { |
<> | 154:37f96f9d4de2 | 1189 | /* Transmit under flow error. */ |
<> | 154:37f96f9d4de2 | 1190 | eErrorStatic->statsTxUnderFlowErr++; |
<> | 154:37f96f9d4de2 | 1191 | } |
<> | 154:37f96f9d4de2 | 1192 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_OVERFLOWERR_MASK) |
<> | 154:37f96f9d4de2 | 1193 | { |
<> | 154:37f96f9d4de2 | 1194 | /* Transmit over flow error. */ |
<> | 154:37f96f9d4de2 | 1195 | eErrorStatic->statsTxOverFlowErr++; |
<> | 154:37f96f9d4de2 | 1196 | } |
<> | 154:37f96f9d4de2 | 1197 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1198 | } |
<> | 154:37f96f9d4de2 | 1199 | |
<> | 154:37f96f9d4de2 | 1200 | } while (handle->txBdDirtyStatic != handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 1201 | |
<> | 154:37f96f9d4de2 | 1202 | return kStatus_ENET_TxFrameFail; |
<> | 154:37f96f9d4de2 | 1203 | } |
<> | 154:37f96f9d4de2 | 1204 | |
<> | 154:37f96f9d4de2 | 1205 | static bool ENET_Ptp1588ParseFrame(uint8_t *data, enet_ptp_time_data_t *ptpTsData, bool isFastEnabled) |
<> | 154:37f96f9d4de2 | 1206 | { |
<> | 154:37f96f9d4de2 | 1207 | assert(data); |
<> | 154:37f96f9d4de2 | 1208 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1209 | { |
<> | 154:37f96f9d4de2 | 1210 | assert(ptpTsData); |
<> | 154:37f96f9d4de2 | 1211 | } |
<> | 154:37f96f9d4de2 | 1212 | |
<> | 154:37f96f9d4de2 | 1213 | bool isPtpMsg = false; |
<> | 154:37f96f9d4de2 | 1214 | uint8_t *buffer = data; |
<> | 154:37f96f9d4de2 | 1215 | uint16_t ptpType; |
<> | 154:37f96f9d4de2 | 1216 | |
<> | 154:37f96f9d4de2 | 1217 | /* Check for VLAN frame. */ |
<> | 154:37f96f9d4de2 | 1218 | if (*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET) == ENET_HTONS(ENET_8021QVLAN)) |
<> | 154:37f96f9d4de2 | 1219 | { |
<> | 154:37f96f9d4de2 | 1220 | buffer += (ENET_FRAME_VLAN_HEADERLEN - ENET_FRAME_HEADERLEN); |
<> | 154:37f96f9d4de2 | 1221 | } |
<> | 154:37f96f9d4de2 | 1222 | |
<> | 154:37f96f9d4de2 | 1223 | ptpType = *(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET); |
<> | 154:37f96f9d4de2 | 1224 | switch (ENET_HTONS(ptpType)) |
<> | 154:37f96f9d4de2 | 1225 | { /* Ethernet layer 2. */ |
<> | 154:37f96f9d4de2 | 1226 | case ENET_ETHERNETL2: |
<> | 154:37f96f9d4de2 | 1227 | if (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_MSGTYPE_OFFSET) <= kENET_PtpEventMsgType) |
<> | 154:37f96f9d4de2 | 1228 | { |
<> | 154:37f96f9d4de2 | 1229 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1230 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1231 | { |
<> | 154:37f96f9d4de2 | 1232 | /* It's a ptpv2 message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1233 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1234 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1235 | ptpTsData->sequenceId = ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1236 | memcpy((void *)&ptpTsData->sourcePortId[0], (void *)(buffer + ENET_PTP1588_ETHL2_CLOCKID_OFFSET), |
<> | 154:37f96f9d4de2 | 1237 | kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1238 | } |
<> | 154:37f96f9d4de2 | 1239 | } |
<> | 154:37f96f9d4de2 | 1240 | break; |
<> | 154:37f96f9d4de2 | 1241 | /* IPV4. */ |
<> | 154:37f96f9d4de2 | 1242 | case ENET_IPV4: |
<> | 154:37f96f9d4de2 | 1243 | if ((*(uint8_t *)(buffer + ENET_PTP1588_IPVERSION_OFFSET) >> 4) == ENET_IPV4VERSION) |
<> | 154:37f96f9d4de2 | 1244 | { |
<> | 154:37f96f9d4de2 | 1245 | if (((*(uint16_t *)(buffer + ENET_PTP1588_IPV4_UDP_PORT_OFFSET)) == ENET_HTONS(kENET_PtpEventPort)) && |
<> | 154:37f96f9d4de2 | 1246 | (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_PROTOCOL_OFFSET) == ENET_UDPVERSION)) |
<> | 154:37f96f9d4de2 | 1247 | { |
<> | 154:37f96f9d4de2 | 1248 | /* Set the PTP message flag. */ |
<> | 154:37f96f9d4de2 | 1249 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1250 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1251 | { |
<> | 154:37f96f9d4de2 | 1252 | /* It's a IPV4 ptp message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1253 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1254 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1255 | ptpTsData->sequenceId = |
<> | 154:37f96f9d4de2 | 1256 | ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_IPV4_UDP_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1257 | memcpy((void *)&ptpTsData->sourcePortId[0], |
<> | 154:37f96f9d4de2 | 1258 | (void *)(buffer + ENET_PTP1588_IPV4_UDP_CLKID_OFFSET), kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1259 | } |
<> | 154:37f96f9d4de2 | 1260 | } |
<> | 154:37f96f9d4de2 | 1261 | } |
<> | 154:37f96f9d4de2 | 1262 | break; |
<> | 154:37f96f9d4de2 | 1263 | /* IPV6. */ |
<> | 154:37f96f9d4de2 | 1264 | case ENET_IPV6: |
<> | 154:37f96f9d4de2 | 1265 | if ((*(uint8_t *)(buffer + ENET_PTP1588_IPVERSION_OFFSET) >> 4) == ENET_IPV6VERSION) |
<> | 154:37f96f9d4de2 | 1266 | { |
<> | 154:37f96f9d4de2 | 1267 | if (((*(uint16_t *)(buffer + ENET_PTP1588_IPV6_UDP_PORT_OFFSET)) == ENET_HTONS(kENET_PtpEventPort)) && |
<> | 154:37f96f9d4de2 | 1268 | (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_PROTOCOL_OFFSET) == ENET_UDPVERSION)) |
<> | 154:37f96f9d4de2 | 1269 | { |
<> | 154:37f96f9d4de2 | 1270 | /* Set the PTP message flag. */ |
<> | 154:37f96f9d4de2 | 1271 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1272 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1273 | { |
<> | 154:37f96f9d4de2 | 1274 | /* It's a IPV6 ptp message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1275 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1276 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1277 | ptpTsData->sequenceId = |
<> | 154:37f96f9d4de2 | 1278 | ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_IPV6_UDP_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1279 | memcpy((void *)&ptpTsData->sourcePortId[0], |
<> | 154:37f96f9d4de2 | 1280 | (void *)(buffer + ENET_PTP1588_IPV6_UDP_CLKID_OFFSET), kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1281 | } |
<> | 154:37f96f9d4de2 | 1282 | } |
<> | 154:37f96f9d4de2 | 1283 | } |
<> | 154:37f96f9d4de2 | 1284 | break; |
<> | 154:37f96f9d4de2 | 1285 | default: |
<> | 154:37f96f9d4de2 | 1286 | break; |
<> | 154:37f96f9d4de2 | 1287 | } |
<> | 154:37f96f9d4de2 | 1288 | return isPtpMsg; |
<> | 154:37f96f9d4de2 | 1289 | } |
<> | 154:37f96f9d4de2 | 1290 | |
<> | 154:37f96f9d4de2 | 1291 | void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_config_t *ptpConfig) |
<> | 154:37f96f9d4de2 | 1292 | { |
<> | 154:37f96f9d4de2 | 1293 | assert(handle); |
<> | 154:37f96f9d4de2 | 1294 | assert(ptpConfig); |
<> | 154:37f96f9d4de2 | 1295 | |
<> | 154:37f96f9d4de2 | 1296 | uint32_t instance = ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 1297 | |
<> | 154:37f96f9d4de2 | 1298 | /* Start the 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1299 | ENET_Ptp1588StartTimer(base, ptpConfig->ptp1588ClockSrc_Hz); |
<> | 154:37f96f9d4de2 | 1300 | |
<> | 154:37f96f9d4de2 | 1301 | /* Enables the time stamp interrupt for the master clock on a device. */ |
<> | 154:37f96f9d4de2 | 1302 | ENET_EnableInterrupts(base, kENET_TsTimerInterrupt); |
<> | 154:37f96f9d4de2 | 1303 | /* Enables only frame interrupt for transmit side to store the transmit |
<> | 154:37f96f9d4de2 | 1304 | frame time-stamp when the whole frame is transmitted out. */ |
<> | 154:37f96f9d4de2 | 1305 | ENET_EnableInterrupts(base, kENET_TxFrameInterrupt); |
<> | 154:37f96f9d4de2 | 1306 | ENET_DisableInterrupts(base, kENET_TxBufferInterrupt); |
<> | 154:37f96f9d4de2 | 1307 | |
<> | 154:37f96f9d4de2 | 1308 | /* Setting the receive and transmit state for transaction. */ |
<> | 154:37f96f9d4de2 | 1309 | handle->rxPtpTsDataRing.ptpTsData = ptpConfig->rxPtpTsData; |
<> | 154:37f96f9d4de2 | 1310 | handle->rxPtpTsDataRing.size = ptpConfig->ptpTsRxBuffNum; |
<> | 154:37f96f9d4de2 | 1311 | handle->rxPtpTsDataRing.front = 0; |
<> | 154:37f96f9d4de2 | 1312 | handle->rxPtpTsDataRing.end = 0; |
<> | 154:37f96f9d4de2 | 1313 | handle->txPtpTsDataRing.ptpTsData = ptpConfig->txPtpTsData; |
<> | 154:37f96f9d4de2 | 1314 | handle->txPtpTsDataRing.size = ptpConfig->ptpTsTxBuffNum; |
<> | 154:37f96f9d4de2 | 1315 | handle->txPtpTsDataRing.front = 0; |
<> | 154:37f96f9d4de2 | 1316 | handle->txPtpTsDataRing.end = 0; |
<> | 154:37f96f9d4de2 | 1317 | handle->msTimerSecond = 0; |
<> | 154:37f96f9d4de2 | 1318 | handle->txBdDirtyTime = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1319 | handle->txBdDirtyStatic = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1320 | |
<> | 154:37f96f9d4de2 | 1321 | /* Set the IRQ handler when the interrupt is enabled. */ |
<> | 154:37f96f9d4de2 | 1322 | s_enetTxIsr = ENET_TransmitIRQHandler; |
<> | 156:95d6b41a828b | 1323 | EnableIRQ(s_enetTsIrqId[instance]); |
<> | 156:95d6b41a828b | 1324 | EnableIRQ(s_enetTxIrqId[instance]); |
<> | 154:37f96f9d4de2 | 1325 | } |
<> | 154:37f96f9d4de2 | 1326 | |
<> | 154:37f96f9d4de2 | 1327 | void ENET_Ptp1588StartTimer(ENET_Type *base, uint32_t ptpClkSrc) |
<> | 154:37f96f9d4de2 | 1328 | { |
<> | 154:37f96f9d4de2 | 1329 | /* Restart PTP 1588 timer, master clock. */ |
<> | 154:37f96f9d4de2 | 1330 | base->ATCR = ENET_ATCR_RESTART_MASK; |
<> | 154:37f96f9d4de2 | 1331 | |
<> | 154:37f96f9d4de2 | 1332 | /* Initializes PTP 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1333 | base->ATINC = ENET_ATINC_INC(ENET_NANOSECOND_ONE_SECOND / ptpClkSrc); |
<> | 154:37f96f9d4de2 | 1334 | base->ATPER = ENET_NANOSECOND_ONE_SECOND; |
<> | 154:37f96f9d4de2 | 1335 | /* Sets periodical event and the event signal output assertion and Actives PTP 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1336 | base->ATCR = ENET_ATCR_PEREN_MASK | ENET_ATCR_PINPER_MASK | ENET_ATCR_EN_MASK; |
<> | 154:37f96f9d4de2 | 1337 | } |
<> | 154:37f96f9d4de2 | 1338 | |
<> | 154:37f96f9d4de2 | 1339 | void ENET_Ptp1588GetTimer(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_t *ptpTime) |
<> | 154:37f96f9d4de2 | 1340 | { |
<> | 154:37f96f9d4de2 | 1341 | assert(handle); |
<> | 154:37f96f9d4de2 | 1342 | assert(ptpTime); |
<> | 154:37f96f9d4de2 | 1343 | uint16_t count = ENET_1588TIME_DELAY_COUNT; |
<> | 154:37f96f9d4de2 | 1344 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1345 | |
<> | 154:37f96f9d4de2 | 1346 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1347 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1348 | |
<> | 154:37f96f9d4de2 | 1349 | /* Get the current PTP time. */ |
<> | 154:37f96f9d4de2 | 1350 | ptpTime->second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1351 | /* Get the nanosecond from the master timer. */ |
<> | 154:37f96f9d4de2 | 1352 | base->ATCR |= ENET_ATCR_CAPTURE_MASK; |
<> | 154:37f96f9d4de2 | 1353 | /* Add at least six clock cycle delay to get accurate time. |
<> | 154:37f96f9d4de2 | 1354 | It's the requirement when the 1588 clock source is slower |
<> | 154:37f96f9d4de2 | 1355 | than the register clock. |
<> | 154:37f96f9d4de2 | 1356 | */ |
<> | 154:37f96f9d4de2 | 1357 | while (count--) |
<> | 154:37f96f9d4de2 | 1358 | { |
<> | 154:37f96f9d4de2 | 1359 | __NOP(); |
<> | 154:37f96f9d4de2 | 1360 | } |
<> | 154:37f96f9d4de2 | 1361 | /* Get the captured time. */ |
<> | 154:37f96f9d4de2 | 1362 | ptpTime->nanosecond = base->ATVR; |
<> | 154:37f96f9d4de2 | 1363 | |
<> | 154:37f96f9d4de2 | 1364 | /* Enables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1365 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1366 | } |
<> | 154:37f96f9d4de2 | 1367 | |
<> | 154:37f96f9d4de2 | 1368 | void ENET_Ptp1588SetTimer(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_t *ptpTime) |
<> | 154:37f96f9d4de2 | 1369 | { |
<> | 154:37f96f9d4de2 | 1370 | assert(handle); |
<> | 154:37f96f9d4de2 | 1371 | assert(ptpTime); |
<> | 154:37f96f9d4de2 | 1372 | |
<> | 154:37f96f9d4de2 | 1373 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1374 | |
<> | 154:37f96f9d4de2 | 1375 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1376 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1377 | |
<> | 154:37f96f9d4de2 | 1378 | /* Sets PTP timer. */ |
<> | 154:37f96f9d4de2 | 1379 | handle->msTimerSecond = ptpTime->second; |
<> | 154:37f96f9d4de2 | 1380 | base->ATVR = ptpTime->nanosecond; |
<> | 154:37f96f9d4de2 | 1381 | |
<> | 154:37f96f9d4de2 | 1382 | /* Enables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1383 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1384 | } |
<> | 154:37f96f9d4de2 | 1385 | |
<> | 154:37f96f9d4de2 | 1386 | void ENET_Ptp1588AdjustTimer(ENET_Type *base, uint32_t corrIncrease, uint32_t corrPeriod) |
<> | 154:37f96f9d4de2 | 1387 | { |
<> | 154:37f96f9d4de2 | 1388 | /* Set correction for PTP timer increment. */ |
<> | 154:37f96f9d4de2 | 1389 | base->ATINC = (base->ATINC & ~ENET_ATINC_INC_CORR_MASK) | (corrIncrease << ENET_ATINC_INC_CORR_SHIFT); |
<> | 154:37f96f9d4de2 | 1390 | /* Set correction for PTP timer period. */ |
<> | 154:37f96f9d4de2 | 1391 | base->ATCOR = (base->ATCOR & ~ENET_ATCOR_COR_MASK) | (corrPeriod << ENET_ATCOR_COR_SHIFT); |
<> | 154:37f96f9d4de2 | 1392 | } |
<> | 154:37f96f9d4de2 | 1393 | |
<> | 154:37f96f9d4de2 | 1394 | static status_t ENET_Ptp1588UpdateTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1395 | { |
<> | 154:37f96f9d4de2 | 1396 | assert(ptpTsDataRing); |
<> | 154:37f96f9d4de2 | 1397 | assert(ptpTsDataRing->ptpTsData); |
<> | 154:37f96f9d4de2 | 1398 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1399 | |
<> | 154:37f96f9d4de2 | 1400 | uint16_t usedBuffer = 0; |
<> | 154:37f96f9d4de2 | 1401 | |
<> | 154:37f96f9d4de2 | 1402 | /* Check if the buffers ring is full. */ |
<> | 154:37f96f9d4de2 | 1403 | if (ptpTsDataRing->end >= ptpTsDataRing->front) |
<> | 154:37f96f9d4de2 | 1404 | { |
<> | 154:37f96f9d4de2 | 1405 | usedBuffer = ptpTsDataRing->end - ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1406 | } |
<> | 154:37f96f9d4de2 | 1407 | else |
<> | 154:37f96f9d4de2 | 1408 | { |
<> | 154:37f96f9d4de2 | 1409 | usedBuffer = ptpTsDataRing->size - (ptpTsDataRing->front - ptpTsDataRing->end); |
<> | 154:37f96f9d4de2 | 1410 | } |
<> | 154:37f96f9d4de2 | 1411 | |
<> | 154:37f96f9d4de2 | 1412 | if (usedBuffer == ptpTsDataRing->size) |
<> | 154:37f96f9d4de2 | 1413 | { |
<> | 154:37f96f9d4de2 | 1414 | return kStatus_ENET_PtpTsRingFull; |
<> | 154:37f96f9d4de2 | 1415 | } |
<> | 154:37f96f9d4de2 | 1416 | |
<> | 154:37f96f9d4de2 | 1417 | /* Copy the new data into the buffer. */ |
<> | 154:37f96f9d4de2 | 1418 | memcpy((ptpTsDataRing->ptpTsData + ptpTsDataRing->end), ptpTimeData, sizeof(enet_ptp_time_data_t)); |
<> | 154:37f96f9d4de2 | 1419 | |
<> | 154:37f96f9d4de2 | 1420 | /* Increase the buffer pointer to the next empty one. */ |
<> | 154:37f96f9d4de2 | 1421 | ptpTsDataRing->end = (ptpTsDataRing->end + 1) % ptpTsDataRing->size; |
<> | 154:37f96f9d4de2 | 1422 | |
<> | 154:37f96f9d4de2 | 1423 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1424 | } |
<> | 154:37f96f9d4de2 | 1425 | |
<> | 154:37f96f9d4de2 | 1426 | static status_t ENET_Ptp1588SearchTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimedata) |
<> | 154:37f96f9d4de2 | 1427 | { |
<> | 154:37f96f9d4de2 | 1428 | assert(ptpTsDataRing); |
<> | 154:37f96f9d4de2 | 1429 | assert(ptpTsDataRing->ptpTsData); |
<> | 154:37f96f9d4de2 | 1430 | assert(ptpTimedata); |
<> | 154:37f96f9d4de2 | 1431 | |
<> | 154:37f96f9d4de2 | 1432 | uint32_t index; |
<> | 154:37f96f9d4de2 | 1433 | uint32_t size; |
<> | 154:37f96f9d4de2 | 1434 | uint16_t usedBuffer = 0; |
<> | 154:37f96f9d4de2 | 1435 | |
<> | 154:37f96f9d4de2 | 1436 | /* Check the PTP 1588 timestamp ring. */ |
<> | 154:37f96f9d4de2 | 1437 | if (ptpTsDataRing->front == ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1438 | { |
<> | 154:37f96f9d4de2 | 1439 | return kStatus_ENET_PtpTsRingEmpty; |
<> | 154:37f96f9d4de2 | 1440 | } |
<> | 154:37f96f9d4de2 | 1441 | |
<> | 154:37f96f9d4de2 | 1442 | /* Search the element in the ring buffer */ |
<> | 154:37f96f9d4de2 | 1443 | index = ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1444 | size = ptpTsDataRing->size; |
<> | 154:37f96f9d4de2 | 1445 | while (index != ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1446 | { |
<> | 154:37f96f9d4de2 | 1447 | if (((ptpTsDataRing->ptpTsData + index)->sequenceId == ptpTimedata->sequenceId) && |
<> | 154:37f96f9d4de2 | 1448 | (!memcmp(((void *)&(ptpTsDataRing->ptpTsData + index)->sourcePortId[0]), |
<> | 154:37f96f9d4de2 | 1449 | (void *)&ptpTimedata->sourcePortId[0], kENET_PtpSrcPortIdLen)) && |
<> | 154:37f96f9d4de2 | 1450 | ((ptpTsDataRing->ptpTsData + index)->version == ptpTimedata->version) && |
<> | 154:37f96f9d4de2 | 1451 | ((ptpTsDataRing->ptpTsData + index)->messageType == ptpTimedata->messageType)) |
<> | 154:37f96f9d4de2 | 1452 | { |
<> | 154:37f96f9d4de2 | 1453 | break; |
<> | 154:37f96f9d4de2 | 1454 | } |
<> | 154:37f96f9d4de2 | 1455 | |
<> | 154:37f96f9d4de2 | 1456 | /* Increase the ptp ring index. */ |
<> | 154:37f96f9d4de2 | 1457 | index = (index + 1) % size; |
<> | 154:37f96f9d4de2 | 1458 | } |
<> | 154:37f96f9d4de2 | 1459 | |
<> | 154:37f96f9d4de2 | 1460 | if (index == ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1461 | { |
<> | 154:37f96f9d4de2 | 1462 | /* Check if buffers is full. */ |
<> | 154:37f96f9d4de2 | 1463 | if (ptpTsDataRing->end >= ptpTsDataRing->front) |
<> | 154:37f96f9d4de2 | 1464 | { |
<> | 154:37f96f9d4de2 | 1465 | usedBuffer = ptpTsDataRing->end - ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1466 | } |
<> | 154:37f96f9d4de2 | 1467 | else |
<> | 154:37f96f9d4de2 | 1468 | { |
<> | 154:37f96f9d4de2 | 1469 | usedBuffer = ptpTsDataRing->size - (ptpTsDataRing->front - ptpTsDataRing->end); |
<> | 154:37f96f9d4de2 | 1470 | } |
<> | 154:37f96f9d4de2 | 1471 | |
<> | 154:37f96f9d4de2 | 1472 | if (usedBuffer == ptpTsDataRing->size) |
<> | 154:37f96f9d4de2 | 1473 | { /* Drop one in the front. */ |
<> | 154:37f96f9d4de2 | 1474 | ptpTsDataRing->front = (ptpTsDataRing->front + 1) % size; |
<> | 154:37f96f9d4de2 | 1475 | } |
<> | 154:37f96f9d4de2 | 1476 | return kStatus_ENET_PtpTsRingFull; |
<> | 154:37f96f9d4de2 | 1477 | } |
<> | 154:37f96f9d4de2 | 1478 | |
<> | 154:37f96f9d4de2 | 1479 | /* Get the right timestamp of the required ptp messag. */ |
<> | 154:37f96f9d4de2 | 1480 | ptpTimedata->timeStamp.second = (ptpTsDataRing->ptpTsData + index)->timeStamp.second; |
<> | 154:37f96f9d4de2 | 1481 | ptpTimedata->timeStamp.nanosecond = (ptpTsDataRing->ptpTsData + index)->timeStamp.nanosecond; |
<> | 154:37f96f9d4de2 | 1482 | |
<> | 154:37f96f9d4de2 | 1483 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 1484 | ptpTsDataRing->front = (ptpTsDataRing->front + 1) % size; |
<> | 154:37f96f9d4de2 | 1485 | |
<> | 154:37f96f9d4de2 | 1486 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1487 | } |
<> | 154:37f96f9d4de2 | 1488 | |
<> | 154:37f96f9d4de2 | 1489 | static status_t ENET_StoreRxFrameTime(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1490 | { |
<> | 154:37f96f9d4de2 | 1491 | assert(handle); |
<> | 154:37f96f9d4de2 | 1492 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1493 | |
<> | 154:37f96f9d4de2 | 1494 | bool ptpTimerWrap = false; |
<> | 154:37f96f9d4de2 | 1495 | enet_ptp_time_t ptpTimer; |
<> | 154:37f96f9d4de2 | 1496 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1497 | |
<> | 154:37f96f9d4de2 | 1498 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1499 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1500 | |
<> | 154:37f96f9d4de2 | 1501 | /* Get current PTP timer nanosecond value. */ |
<> | 154:37f96f9d4de2 | 1502 | ENET_Ptp1588GetTimer(base, handle, &ptpTimer); |
<> | 154:37f96f9d4de2 | 1503 | |
<> | 154:37f96f9d4de2 | 1504 | /* Get PTP timer wrap event. */ |
<> | 154:37f96f9d4de2 | 1505 | ptpTimerWrap = base->EIR & kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1506 | |
<> | 154:37f96f9d4de2 | 1507 | /* Get transmit time stamp second. */ |
<> | 154:37f96f9d4de2 | 1508 | if ((ptpTimer.nanosecond > ptpTimeData->timeStamp.nanosecond) || |
<> | 154:37f96f9d4de2 | 1509 | ((ptpTimer.nanosecond < ptpTimeData->timeStamp.nanosecond) && ptpTimerWrap)) |
<> | 154:37f96f9d4de2 | 1510 | { |
<> | 154:37f96f9d4de2 | 1511 | ptpTimeData->timeStamp.second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1512 | } |
<> | 154:37f96f9d4de2 | 1513 | else |
<> | 154:37f96f9d4de2 | 1514 | { |
<> | 154:37f96f9d4de2 | 1515 | ptpTimeData->timeStamp.second = handle->msTimerSecond - 1; |
<> | 154:37f96f9d4de2 | 1516 | } |
<> | 154:37f96f9d4de2 | 1517 | /* Enable the interrupt. */ |
<> | 154:37f96f9d4de2 | 1518 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1519 | |
<> | 154:37f96f9d4de2 | 1520 | /* Store the timestamp to the receive time stamp ring. */ |
<> | 154:37f96f9d4de2 | 1521 | /* Check if the buffers ring is full. */ |
<> | 154:37f96f9d4de2 | 1522 | return ENET_Ptp1588UpdateTimeRing(&handle->rxPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1523 | } |
<> | 154:37f96f9d4de2 | 1524 | |
<> | 154:37f96f9d4de2 | 1525 | static status_t ENET_StoreTxFrameTime(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1526 | { |
<> | 154:37f96f9d4de2 | 1527 | assert(handle); |
<> | 154:37f96f9d4de2 | 1528 | |
<> | 154:37f96f9d4de2 | 1529 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1530 | bool ptpTimerWrap; |
<> | 154:37f96f9d4de2 | 1531 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 1532 | enet_ptp_time_data_t ptpTimeData; |
<> | 154:37f96f9d4de2 | 1533 | volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdDirtyTime; |
<> | 154:37f96f9d4de2 | 1534 | |
<> | 154:37f96f9d4de2 | 1535 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1536 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1537 | { |
<> | 154:37f96f9d4de2 | 1538 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1539 | } |
<> | 154:37f96f9d4de2 | 1540 | |
<> | 154:37f96f9d4de2 | 1541 | /* Parse the PTP message. */ |
<> | 154:37f96f9d4de2 | 1542 | isPtpEventMessage = ENET_Ptp1588ParseFrame(curBuffDescrip->buffer, &ptpTimeData, false); |
<> | 154:37f96f9d4de2 | 1543 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 1544 | { |
<> | 154:37f96f9d4de2 | 1545 | do |
<> | 154:37f96f9d4de2 | 1546 | { |
<> | 154:37f96f9d4de2 | 1547 | /* Increase current buffer descriptor to the next one. */ |
<> | 154:37f96f9d4de2 | 1548 | if (handle->txBdDirtyTime->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1549 | { |
<> | 154:37f96f9d4de2 | 1550 | handle->txBdDirtyTime = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1551 | } |
<> | 154:37f96f9d4de2 | 1552 | else |
<> | 154:37f96f9d4de2 | 1553 | { |
<> | 154:37f96f9d4de2 | 1554 | handle->txBdDirtyTime++; |
<> | 154:37f96f9d4de2 | 1555 | } |
<> | 154:37f96f9d4de2 | 1556 | |
<> | 154:37f96f9d4de2 | 1557 | /* Do time stamp check on the last buffer descriptor of the frame. */ |
<> | 154:37f96f9d4de2 | 1558 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 1559 | { |
<> | 154:37f96f9d4de2 | 1560 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1561 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1562 | |
<> | 154:37f96f9d4de2 | 1563 | /* Get current PTP timer nanosecond value. */ |
<> | 154:37f96f9d4de2 | 1564 | ENET_Ptp1588GetTimer(base, handle, &ptpTimeData.timeStamp); |
<> | 154:37f96f9d4de2 | 1565 | |
<> | 154:37f96f9d4de2 | 1566 | /* Get PTP timer wrap event. */ |
<> | 154:37f96f9d4de2 | 1567 | ptpTimerWrap = base->EIR & kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1568 | |
<> | 154:37f96f9d4de2 | 1569 | /* Get transmit time stamp second. */ |
<> | 154:37f96f9d4de2 | 1570 | if ((ptpTimeData.timeStamp.nanosecond > curBuffDescrip->timestamp) || |
<> | 154:37f96f9d4de2 | 1571 | ((ptpTimeData.timeStamp.nanosecond < curBuffDescrip->timestamp) && ptpTimerWrap)) |
<> | 154:37f96f9d4de2 | 1572 | { |
<> | 154:37f96f9d4de2 | 1573 | ptpTimeData.timeStamp.second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1574 | } |
<> | 154:37f96f9d4de2 | 1575 | else |
<> | 154:37f96f9d4de2 | 1576 | { |
<> | 154:37f96f9d4de2 | 1577 | ptpTimeData.timeStamp.second = handle->msTimerSecond - 1; |
<> | 154:37f96f9d4de2 | 1578 | } |
<> | 154:37f96f9d4de2 | 1579 | |
<> | 154:37f96f9d4de2 | 1580 | /* Enable the interrupt. */ |
<> | 154:37f96f9d4de2 | 1581 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1582 | |
<> | 154:37f96f9d4de2 | 1583 | /* Store the timestamp to the transmit timestamp ring. */ |
<> | 154:37f96f9d4de2 | 1584 | return ENET_Ptp1588UpdateTimeRing(&handle->txPtpTsDataRing, &ptpTimeData); |
<> | 154:37f96f9d4de2 | 1585 | } |
<> | 154:37f96f9d4de2 | 1586 | |
<> | 154:37f96f9d4de2 | 1587 | /* Get the current transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1588 | curBuffDescrip = handle->txBdDirtyTime; |
<> | 154:37f96f9d4de2 | 1589 | |
<> | 154:37f96f9d4de2 | 1590 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1591 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1592 | { |
<> | 154:37f96f9d4de2 | 1593 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1594 | } |
<> | 154:37f96f9d4de2 | 1595 | } while (handle->txBdDirtyTime != handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 1596 | return kStatus_ENET_TxFrameFail; |
<> | 154:37f96f9d4de2 | 1597 | } |
<> | 154:37f96f9d4de2 | 1598 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1599 | } |
<> | 154:37f96f9d4de2 | 1600 | |
<> | 154:37f96f9d4de2 | 1601 | status_t ENET_GetTxFrameTime(enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1602 | { |
<> | 154:37f96f9d4de2 | 1603 | assert(handle); |
<> | 154:37f96f9d4de2 | 1604 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1605 | |
<> | 154:37f96f9d4de2 | 1606 | return ENET_Ptp1588SearchTimeRing(&handle->txPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1607 | } |
<> | 154:37f96f9d4de2 | 1608 | |
<> | 154:37f96f9d4de2 | 1609 | status_t ENET_GetRxFrameTime(enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1610 | { |
<> | 154:37f96f9d4de2 | 1611 | assert(handle); |
<> | 154:37f96f9d4de2 | 1612 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1613 | |
<> | 154:37f96f9d4de2 | 1614 | return ENET_Ptp1588SearchTimeRing(&handle->rxPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1615 | } |
<> | 154:37f96f9d4de2 | 1616 | |
<> | 154:37f96f9d4de2 | 1617 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1618 | |
<> | 154:37f96f9d4de2 | 1619 | void ENET_TransmitIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1620 | { |
<> | 154:37f96f9d4de2 | 1621 | assert(handle); |
<> | 154:37f96f9d4de2 | 1622 | |
<> | 154:37f96f9d4de2 | 1623 | /* Check if the transmit interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1624 | while ((kENET_TxBufferInterrupt | kENET_TxFrameInterrupt) & base->EIR) |
<> | 154:37f96f9d4de2 | 1625 | { |
<> | 154:37f96f9d4de2 | 1626 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1627 | if (base->EIR & kENET_TxFrameInterrupt) |
<> | 154:37f96f9d4de2 | 1628 | { |
<> | 154:37f96f9d4de2 | 1629 | /* Store the transmit timestamp from the buffer descriptor should be done here. */ |
<> | 154:37f96f9d4de2 | 1630 | ENET_StoreTxFrameTime(base, handle); |
<> | 154:37f96f9d4de2 | 1631 | } |
<> | 154:37f96f9d4de2 | 1632 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1633 | |
<> | 154:37f96f9d4de2 | 1634 | /* Clear the transmit interrupt event. */ |
<> | 154:37f96f9d4de2 | 1635 | base->EIR = kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; |
<> | 154:37f96f9d4de2 | 1636 | |
<> | 154:37f96f9d4de2 | 1637 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1638 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1639 | { |
<> | 154:37f96f9d4de2 | 1640 | handle->callback(base, handle, kENET_TxEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1641 | } |
<> | 154:37f96f9d4de2 | 1642 | } |
<> | 154:37f96f9d4de2 | 1643 | } |
<> | 154:37f96f9d4de2 | 1644 | |
<> | 154:37f96f9d4de2 | 1645 | void ENET_ReceiveIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1646 | { |
<> | 154:37f96f9d4de2 | 1647 | assert(handle); |
<> | 154:37f96f9d4de2 | 1648 | |
<> | 154:37f96f9d4de2 | 1649 | /* Check if the receive interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1650 | while ((kENET_RxBufferInterrupt | kENET_RxFrameInterrupt) & base->EIR) |
<> | 154:37f96f9d4de2 | 1651 | { |
<> | 154:37f96f9d4de2 | 1652 | /* Clear the transmit interrupt event. */ |
<> | 154:37f96f9d4de2 | 1653 | base->EIR = kENET_RxFrameInterrupt | kENET_RxBufferInterrupt; |
<> | 154:37f96f9d4de2 | 1654 | |
<> | 154:37f96f9d4de2 | 1655 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1656 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1657 | { |
<> | 154:37f96f9d4de2 | 1658 | handle->callback(base, handle, kENET_RxEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1659 | } |
<> | 154:37f96f9d4de2 | 1660 | } |
<> | 154:37f96f9d4de2 | 1661 | } |
<> | 154:37f96f9d4de2 | 1662 | |
<> | 154:37f96f9d4de2 | 1663 | void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1664 | { |
<> | 154:37f96f9d4de2 | 1665 | assert(handle); |
<> | 154:37f96f9d4de2 | 1666 | |
<> | 154:37f96f9d4de2 | 1667 | uint32_t errMask = kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | kENET_PayloadRxInterrupt | |
<> | 154:37f96f9d4de2 | 1668 | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt; |
<> | 154:37f96f9d4de2 | 1669 | |
<> | 154:37f96f9d4de2 | 1670 | /* Check if the error interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1671 | if (kENET_WakeupInterrupt & base->EIR) |
<> | 154:37f96f9d4de2 | 1672 | { |
<> | 154:37f96f9d4de2 | 1673 | /* Clear the wakeup interrupt. */ |
<> | 154:37f96f9d4de2 | 1674 | base->EIR = kENET_WakeupInterrupt; |
<> | 154:37f96f9d4de2 | 1675 | /* wake up and enter the normal mode. */ |
<> | 154:37f96f9d4de2 | 1676 | ENET_EnableSleepMode(base, false); |
<> | 154:37f96f9d4de2 | 1677 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1678 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1679 | { |
<> | 154:37f96f9d4de2 | 1680 | handle->callback(base, handle, kENET_WakeUpEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1681 | } |
<> | 154:37f96f9d4de2 | 1682 | } |
<> | 154:37f96f9d4de2 | 1683 | else |
<> | 154:37f96f9d4de2 | 1684 | { |
<> | 154:37f96f9d4de2 | 1685 | /* Clear the error interrupt event status. */ |
<> | 154:37f96f9d4de2 | 1686 | errMask &= base->EIR; |
<> | 154:37f96f9d4de2 | 1687 | base->EIR = errMask; |
<> | 154:37f96f9d4de2 | 1688 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1689 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1690 | { |
<> | 154:37f96f9d4de2 | 1691 | handle->callback(base, handle, kENET_ErrEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1692 | } |
<> | 154:37f96f9d4de2 | 1693 | } |
<> | 154:37f96f9d4de2 | 1694 | } |
<> | 154:37f96f9d4de2 | 1695 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1696 | void ENET_Ptp1588TimerIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1697 | { |
<> | 154:37f96f9d4de2 | 1698 | assert(handle); |
<> | 154:37f96f9d4de2 | 1699 | |
<> | 154:37f96f9d4de2 | 1700 | /* Check if the PTP time stamp interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1701 | if (kENET_TsTimerInterrupt & base->EIR) |
<> | 154:37f96f9d4de2 | 1702 | { |
<> | 154:37f96f9d4de2 | 1703 | /* Clear the time stamp interrupt. */ |
<> | 154:37f96f9d4de2 | 1704 | base->EIR = kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1705 | |
<> | 154:37f96f9d4de2 | 1706 | /* Increase timer second counter. */ |
<> | 154:37f96f9d4de2 | 1707 | handle->msTimerSecond++; |
<> | 154:37f96f9d4de2 | 1708 | |
<> | 154:37f96f9d4de2 | 1709 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1710 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1711 | { |
<> | 154:37f96f9d4de2 | 1712 | handle->callback(base, handle, kENET_TimeStampEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1713 | } |
<> | 154:37f96f9d4de2 | 1714 | } |
<> | 154:37f96f9d4de2 | 1715 | else |
<> | 154:37f96f9d4de2 | 1716 | { |
<> | 154:37f96f9d4de2 | 1717 | /* Clear the time stamp interrupt. */ |
<> | 154:37f96f9d4de2 | 1718 | base->EIR = kENET_TsAvailInterrupt; |
<> | 154:37f96f9d4de2 | 1719 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1720 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1721 | { |
<> | 154:37f96f9d4de2 | 1722 | handle->callback(base, handle, kENET_TimeStampAvailEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1723 | } |
<> | 154:37f96f9d4de2 | 1724 | } |
<> | 154:37f96f9d4de2 | 1725 | } |
<> | 154:37f96f9d4de2 | 1726 | |
<> | 154:37f96f9d4de2 | 1727 | void ENET_1588_Timer_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1728 | { |
<> | 154:37f96f9d4de2 | 1729 | ENET_Ptp1588TimerIRQHandler(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1730 | } |
<> | 154:37f96f9d4de2 | 1731 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1732 | |
<> | 154:37f96f9d4de2 | 1733 | void ENET_Transmit_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1734 | { |
<> | 154:37f96f9d4de2 | 1735 | s_enetTxIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1736 | } |
<> | 154:37f96f9d4de2 | 1737 | |
<> | 154:37f96f9d4de2 | 1738 | void ENET_Receive_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1739 | { |
<> | 154:37f96f9d4de2 | 1740 | s_enetRxIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1741 | } |
<> | 154:37f96f9d4de2 | 1742 | |
<> | 154:37f96f9d4de2 | 1743 | void ENET_Error_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1744 | { |
<> | 154:37f96f9d4de2 | 1745 | s_enetErrIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1746 | } |