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@156:95d6b41a828b, 2017-01-16 (annotated)
- Committer:
- <>
- Date:
- Mon Jan 16 15:03:32 2017 +0000
- Revision:
- 156:95d6b41a828b
- Parent:
- 154:37f96f9d4de2
- Child:
- 169:e3b6fe271b81
This updates the lib to the mbed lib v134
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 | uint32_t instance = ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 320 | |
<> | 154:37f96f9d4de2 | 321 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 322 | /* Ungate ENET clock. */ |
<> | 154:37f96f9d4de2 | 323 | CLOCK_EnableClock(s_enetClock[instance]); |
<> | 154:37f96f9d4de2 | 324 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 325 | |
<> | 154:37f96f9d4de2 | 326 | /* Reset ENET module. */ |
<> | 154:37f96f9d4de2 | 327 | ENET_Reset(base); |
<> | 154:37f96f9d4de2 | 328 | |
<> | 154:37f96f9d4de2 | 329 | /* Initializes the ENET transmit buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 330 | ENET_SetTxBufferDescriptors(bufferConfig->txBdStartAddrAlign, bufferConfig->txBufferAlign, |
<> | 154:37f96f9d4de2 | 331 | bufferConfig->txBuffSizeAlign, bufferConfig->txBdNumber); |
<> | 154:37f96f9d4de2 | 332 | |
<> | 154:37f96f9d4de2 | 333 | /* Initializes the ENET receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 334 | ENET_SetRxBufferDescriptors(bufferConfig->rxBdStartAddrAlign, bufferConfig->rxBufferAlign, |
<> | 154:37f96f9d4de2 | 335 | bufferConfig->rxBuffSizeAlign, bufferConfig->rxBdNumber, |
<> | 154:37f96f9d4de2 | 336 | !!(config->interrupt & (kENET_RxFrameInterrupt | kENET_RxBufferInterrupt))); |
<> | 154:37f96f9d4de2 | 337 | |
<> | 154:37f96f9d4de2 | 338 | /* Initializes the ENET MAC controller. */ |
<> | 154:37f96f9d4de2 | 339 | ENET_SetMacController(base, config, bufferConfig, macAddr, srcClock_Hz); |
<> | 154:37f96f9d4de2 | 340 | |
<> | 156:95d6b41a828b | 341 | /* Set all buffers or data in handler for data transmit/receive process. */ |
<> | 156:95d6b41a828b | 342 | ENET_SetHandler(base, handle, config, bufferConfig); |
<> | 154:37f96f9d4de2 | 343 | } |
<> | 154:37f96f9d4de2 | 344 | |
<> | 154:37f96f9d4de2 | 345 | void ENET_Deinit(ENET_Type *base) |
<> | 154:37f96f9d4de2 | 346 | { |
<> | 154:37f96f9d4de2 | 347 | /* Disable interrupt. */ |
<> | 154:37f96f9d4de2 | 348 | base->EIMR = 0; |
<> | 154:37f96f9d4de2 | 349 | |
<> | 154:37f96f9d4de2 | 350 | /* Disable ENET. */ |
<> | 154:37f96f9d4de2 | 351 | base->ECR &= ~ENET_ECR_ETHEREN_MASK; |
<> | 154:37f96f9d4de2 | 352 | |
<> | 154:37f96f9d4de2 | 353 | #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
<> | 154:37f96f9d4de2 | 354 | /* Disables the clock source. */ |
<> | 154:37f96f9d4de2 | 355 | CLOCK_DisableClock(s_enetClock[ENET_GetInstance(base)]); |
<> | 154:37f96f9d4de2 | 356 | #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
<> | 154:37f96f9d4de2 | 357 | } |
<> | 154:37f96f9d4de2 | 358 | |
<> | 154:37f96f9d4de2 | 359 | void ENET_SetCallback(enet_handle_t *handle, enet_callback_t callback, void *userData) |
<> | 154:37f96f9d4de2 | 360 | { |
<> | 154:37f96f9d4de2 | 361 | assert(handle); |
<> | 154:37f96f9d4de2 | 362 | |
<> | 154:37f96f9d4de2 | 363 | /* Set callback and userData. */ |
<> | 154:37f96f9d4de2 | 364 | handle->callback = callback; |
<> | 154:37f96f9d4de2 | 365 | handle->userData = userData; |
<> | 154:37f96f9d4de2 | 366 | } |
<> | 154:37f96f9d4de2 | 367 | |
<> | 156:95d6b41a828b | 368 | static void ENET_SetHandler(ENET_Type *base, |
<> | 156:95d6b41a828b | 369 | enet_handle_t *handle, |
<> | 156:95d6b41a828b | 370 | const enet_config_t *config, |
<> | 156:95d6b41a828b | 371 | const enet_buffer_config_t *bufferConfig) |
<> | 156:95d6b41a828b | 372 | { |
<> | 156:95d6b41a828b | 373 | uint32_t instance = ENET_GetInstance(base); |
<> | 156:95d6b41a828b | 374 | |
<> | 156:95d6b41a828b | 375 | memset(handle, 0, sizeof(enet_handle_t)); |
<> | 156:95d6b41a828b | 376 | |
<> | 156:95d6b41a828b | 377 | handle->rxBdBase = bufferConfig->rxBdStartAddrAlign; |
<> | 156:95d6b41a828b | 378 | handle->rxBdCurrent = bufferConfig->rxBdStartAddrAlign; |
<> | 156:95d6b41a828b | 379 | handle->txBdBase = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 380 | handle->txBdCurrent = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 381 | handle->txBdDirty = bufferConfig->txBdStartAddrAlign; |
<> | 156:95d6b41a828b | 382 | handle->rxBuffSizeAlign = bufferConfig->rxBuffSizeAlign; |
<> | 156:95d6b41a828b | 383 | handle->txBuffSizeAlign = bufferConfig->txBuffSizeAlign; |
<> | 156:95d6b41a828b | 384 | |
<> | 156:95d6b41a828b | 385 | /* Save the handle pointer in the global variables. */ |
<> | 156:95d6b41a828b | 386 | s_ENETHandle[instance] = handle; |
<> | 156:95d6b41a828b | 387 | |
<> | 156:95d6b41a828b | 388 | /* Set the IRQ handler when the interrupt is enabled. */ |
<> | 156:95d6b41a828b | 389 | if (config->interrupt & ENET_TX_INTERRUPT) |
<> | 156:95d6b41a828b | 390 | { |
<> | 156:95d6b41a828b | 391 | s_enetTxIsr = ENET_TransmitIRQHandler; |
<> | 156:95d6b41a828b | 392 | EnableIRQ(s_enetTxIrqId[instance]); |
<> | 156:95d6b41a828b | 393 | } |
<> | 156:95d6b41a828b | 394 | if (config->interrupt & ENET_RX_INTERRUPT) |
<> | 156:95d6b41a828b | 395 | { |
<> | 156:95d6b41a828b | 396 | s_enetRxIsr = ENET_ReceiveIRQHandler; |
<> | 156:95d6b41a828b | 397 | EnableIRQ(s_enetRxIrqId[instance]); |
<> | 156:95d6b41a828b | 398 | } |
<> | 156:95d6b41a828b | 399 | if (config->interrupt & ENET_ERR_INTERRUPT) |
<> | 156:95d6b41a828b | 400 | { |
<> | 156:95d6b41a828b | 401 | s_enetErrIsr = ENET_ErrorIRQHandler; |
<> | 156:95d6b41a828b | 402 | EnableIRQ(s_enetErrIrqId[instance]); |
<> | 156:95d6b41a828b | 403 | } |
<> | 156:95d6b41a828b | 404 | } |
<> | 156:95d6b41a828b | 405 | |
<> | 154:37f96f9d4de2 | 406 | static void ENET_SetMacController(ENET_Type *base, |
<> | 154:37f96f9d4de2 | 407 | const enet_config_t *config, |
<> | 154:37f96f9d4de2 | 408 | const enet_buffer_config_t *bufferConfig, |
<> | 154:37f96f9d4de2 | 409 | uint8_t *macAddr, |
<> | 154:37f96f9d4de2 | 410 | uint32_t srcClock_Hz) |
<> | 154:37f96f9d4de2 | 411 | { |
<> | 154:37f96f9d4de2 | 412 | uint32_t rcr = 0; |
<> | 154:37f96f9d4de2 | 413 | uint32_t tcr = 0; |
<> | 154:37f96f9d4de2 | 414 | uint32_t ecr = 0; |
<> | 154:37f96f9d4de2 | 415 | uint32_t macSpecialConfig = config->macSpecialConfig; |
<> | 154:37f96f9d4de2 | 416 | uint32_t instance = ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 417 | |
<> | 154:37f96f9d4de2 | 418 | /* Configures MAC receive controller with user configure structure. */ |
<> | 154:37f96f9d4de2 | 419 | rcr = ENET_RCR_NLC(!!(macSpecialConfig & kENET_ControlRxPayloadCheckEnable)) | |
<> | 154:37f96f9d4de2 | 420 | ENET_RCR_CFEN(!!(macSpecialConfig & kENET_ControlFlowControlEnable)) | |
<> | 154:37f96f9d4de2 | 421 | ENET_RCR_FCE(!!(macSpecialConfig & kENET_ControlFlowControlEnable)) | |
<> | 154:37f96f9d4de2 | 422 | ENET_RCR_PADEN(!!(macSpecialConfig & kENET_ControlRxPadRemoveEnable)) | |
<> | 154:37f96f9d4de2 | 423 | ENET_RCR_BC_REJ(!!(macSpecialConfig & kENET_ControlRxBroadCastRejectEnable)) | |
<> | 154:37f96f9d4de2 | 424 | ENET_RCR_PROM(!!(macSpecialConfig & kENET_ControlPromiscuousEnable)) | ENET_RCR_MII_MODE(1) | |
<> | 154:37f96f9d4de2 | 425 | ENET_RCR_RMII_MODE(config->miiMode) | ENET_RCR_RMII_10T(!config->miiSpeed) | |
<> | 154:37f96f9d4de2 | 426 | ENET_RCR_MAX_FL(config->rxMaxFrameLen) | ENET_RCR_CRCFWD(1); |
<> | 154:37f96f9d4de2 | 427 | /* Receive setting for half duplex. */ |
<> | 154:37f96f9d4de2 | 428 | if (config->miiDuplex == kENET_MiiHalfDuplex) |
<> | 154:37f96f9d4de2 | 429 | { |
<> | 154:37f96f9d4de2 | 430 | rcr |= ENET_RCR_DRT(1); |
<> | 154:37f96f9d4de2 | 431 | } |
<> | 154:37f96f9d4de2 | 432 | /* Sets internal loop only for MII mode. */ |
<> | 154:37f96f9d4de2 | 433 | if ((config->macSpecialConfig & kENET_ControlMIILoopEnable) && (config->miiMode == kENET_MiiMode)) |
<> | 154:37f96f9d4de2 | 434 | { |
<> | 154:37f96f9d4de2 | 435 | rcr |= ENET_RCR_LOOP(1); |
<> | 154:37f96f9d4de2 | 436 | rcr &= ~ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 437 | } |
<> | 154:37f96f9d4de2 | 438 | base->RCR = rcr; |
<> | 154:37f96f9d4de2 | 439 | |
<> | 154:37f96f9d4de2 | 440 | /* Configures MAC transmit controller: duplex mode, mac address insertion. */ |
<> | 154:37f96f9d4de2 | 441 | tcr = base->TCR & ~(ENET_TCR_FDEN_MASK | ENET_TCR_ADDINS_MASK); |
<> | 154:37f96f9d4de2 | 442 | tcr |= ENET_TCR_FDEN(config->miiDuplex) | ENET_TCR_ADDINS(!!(macSpecialConfig & kENET_ControlMacAddrInsert)); |
<> | 154:37f96f9d4de2 | 443 | base->TCR = tcr; |
<> | 154:37f96f9d4de2 | 444 | |
<> | 154:37f96f9d4de2 | 445 | /* Configures receive and transmit accelerator. */ |
<> | 154:37f96f9d4de2 | 446 | base->TACC = config->txAccelerConfig; |
<> | 154:37f96f9d4de2 | 447 | base->RACC = config->rxAccelerConfig; |
<> | 154:37f96f9d4de2 | 448 | |
<> | 154:37f96f9d4de2 | 449 | /* Sets the pause duration and FIFO threshold for the flow control enabled case. */ |
<> | 154:37f96f9d4de2 | 450 | if (macSpecialConfig & kENET_ControlFlowControlEnable) |
<> | 154:37f96f9d4de2 | 451 | { |
<> | 154:37f96f9d4de2 | 452 | uint32_t reemReg; |
<> | 154:37f96f9d4de2 | 453 | base->OPD = config->pauseDuration; |
<> | 154:37f96f9d4de2 | 454 | reemReg = ENET_RSEM_RX_SECTION_EMPTY(config->rxFifoEmptyThreshold); |
<> | 154:37f96f9d4de2 | 455 | #if FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD |
<> | 154:37f96f9d4de2 | 456 | reemReg |= ENET_RSEM_STAT_SECTION_EMPTY(config->rxFifoStatEmptyThreshold); |
<> | 154:37f96f9d4de2 | 457 | #endif /* FSL_FEATURE_ENET_HAS_RECEIVE_STATUS_THRESHOLD */ |
<> | 154:37f96f9d4de2 | 458 | base->RSEM = reemReg; |
<> | 154:37f96f9d4de2 | 459 | } |
<> | 154:37f96f9d4de2 | 460 | |
<> | 154:37f96f9d4de2 | 461 | /* FIFO threshold setting for store and forward enable/disable case. */ |
<> | 154:37f96f9d4de2 | 462 | if (macSpecialConfig & kENET_ControlStoreAndFwdDisable) |
<> | 154:37f96f9d4de2 | 463 | { |
<> | 154:37f96f9d4de2 | 464 | /* Transmit fifo watermark settings. */ |
<> | 154:37f96f9d4de2 | 465 | base->TFWR = config->txFifoWatermark & ENET_TFWR_TFWR_MASK; |
<> | 154:37f96f9d4de2 | 466 | /* Receive fifo full threshold settings. */ |
<> | 154:37f96f9d4de2 | 467 | base->RSFL = config->rxFifoFullThreshold & ENET_RSFL_RX_SECTION_FULL_MASK; |
<> | 154:37f96f9d4de2 | 468 | } |
<> | 154:37f96f9d4de2 | 469 | else |
<> | 154:37f96f9d4de2 | 470 | { |
<> | 154:37f96f9d4de2 | 471 | /* Transmit fifo watermark settings. */ |
<> | 154:37f96f9d4de2 | 472 | base->TFWR = ENET_TFWR_STRFWD_MASK; |
<> | 154:37f96f9d4de2 | 473 | base->RSFL = 0; |
<> | 154:37f96f9d4de2 | 474 | } |
<> | 154:37f96f9d4de2 | 475 | |
<> | 154:37f96f9d4de2 | 476 | /* Enable store and forward when accelerator is enabled */ |
<> | 154:37f96f9d4de2 | 477 | if (config->txAccelerConfig & (kENET_TxAccelIpCheckEnabled | kENET_TxAccelProtoCheckEnabled)) |
<> | 154:37f96f9d4de2 | 478 | { |
<> | 154:37f96f9d4de2 | 479 | base->TFWR = ENET_TFWR_STRFWD_MASK; |
<> | 154:37f96f9d4de2 | 480 | } |
<> | 154:37f96f9d4de2 | 481 | if (config->rxAccelerConfig & (kENET_RxAccelIpCheckEnabled | kENET_RxAccelProtoCheckEnabled)) |
<> | 154:37f96f9d4de2 | 482 | { |
<> | 154:37f96f9d4de2 | 483 | base->RSFL = 0; |
<> | 154:37f96f9d4de2 | 484 | } |
<> | 154:37f96f9d4de2 | 485 | |
<> | 154:37f96f9d4de2 | 486 | /* Initializes transmit buffer descriptor rings start address, two start address should be aligned. */ |
<> | 154:37f96f9d4de2 | 487 | base->TDSR = (uint32_t)bufferConfig->txBdStartAddrAlign; |
<> | 154:37f96f9d4de2 | 488 | base->RDSR = (uint32_t)bufferConfig->rxBdStartAddrAlign; |
<> | 154:37f96f9d4de2 | 489 | /* Initializes the maximum buffer size, the buffer size should be aligned. */ |
<> | 154:37f96f9d4de2 | 490 | base->MRBR = bufferConfig->rxBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 491 | |
<> | 154:37f96f9d4de2 | 492 | /* Configures the Mac address. */ |
<> | 154:37f96f9d4de2 | 493 | ENET_SetMacAddr(base, macAddr); |
<> | 154:37f96f9d4de2 | 494 | |
<> | 154:37f96f9d4de2 | 495 | /* Initialize the SMI if uninitialized. */ |
<> | 154:37f96f9d4de2 | 496 | if (!ENET_GetSMI(base)) |
<> | 154:37f96f9d4de2 | 497 | { |
<> | 154:37f96f9d4de2 | 498 | ENET_SetSMI(base, srcClock_Hz, !!(config->macSpecialConfig & kENET_ControlSMIPreambleDisable)); |
<> | 154:37f96f9d4de2 | 499 | } |
<> | 154:37f96f9d4de2 | 500 | |
<> | 154:37f96f9d4de2 | 501 | /* Enables Ethernet interrupt and NVIC. */ |
<> | 154:37f96f9d4de2 | 502 | ENET_EnableInterrupts(base, config->interrupt); |
<> | 154:37f96f9d4de2 | 503 | |
<> | 154:37f96f9d4de2 | 504 | /* ENET control register setting. */ |
<> | 154:37f96f9d4de2 | 505 | ecr = base->ECR; |
<> | 154:37f96f9d4de2 | 506 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 507 | /* Sets the 1588 enhanced feature. */ |
<> | 154:37f96f9d4de2 | 508 | ecr |= ENET_ECR_EN1588_MASK; |
<> | 154:37f96f9d4de2 | 509 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 510 | /* Enables Ethernet module after all configuration except the buffer descriptor active. */ |
<> | 154:37f96f9d4de2 | 511 | ecr |= ENET_ECR_ETHEREN_MASK | ENET_ECR_DBSWP_MASK; |
<> | 154:37f96f9d4de2 | 512 | base->ECR = ecr; |
<> | 154:37f96f9d4de2 | 513 | } |
<> | 154:37f96f9d4de2 | 514 | |
<> | 154:37f96f9d4de2 | 515 | static void ENET_SetTxBufferDescriptors(volatile enet_tx_bd_struct_t *txBdStartAlign, |
<> | 154:37f96f9d4de2 | 516 | uint8_t *txBuffStartAlign, |
<> | 154:37f96f9d4de2 | 517 | uint32_t txBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 518 | uint32_t txBdNumber) |
<> | 154:37f96f9d4de2 | 519 | { |
<> | 154:37f96f9d4de2 | 520 | assert(txBdStartAlign); |
<> | 154:37f96f9d4de2 | 521 | |
<> | 154:37f96f9d4de2 | 522 | uint32_t count; |
<> | 154:37f96f9d4de2 | 523 | volatile enet_tx_bd_struct_t *curBuffDescrip = txBdStartAlign; |
<> | 154:37f96f9d4de2 | 524 | |
<> | 154:37f96f9d4de2 | 525 | for (count = 0; count < txBdNumber; count++) |
<> | 154:37f96f9d4de2 | 526 | { |
<> | 156:95d6b41a828b | 527 | if (txBuffStartAlign != NULL) |
<> | 154:37f96f9d4de2 | 528 | { |
<> | 154:37f96f9d4de2 | 529 | /* Set data buffer address. */ |
<> | 154:37f96f9d4de2 | 530 | curBuffDescrip->buffer = (uint8_t *)((uint32_t)&txBuffStartAlign[count * txBuffSizeAlign]); |
<> | 154:37f96f9d4de2 | 531 | } |
<> | 154:37f96f9d4de2 | 532 | else |
<> | 154:37f96f9d4de2 | 533 | { |
<> | 154:37f96f9d4de2 | 534 | /* User should provide the transmit buffer at a later time */ |
<> | 154:37f96f9d4de2 | 535 | curBuffDescrip->buffer = NULL; |
<> | 154:37f96f9d4de2 | 536 | } |
<> | 154:37f96f9d4de2 | 537 | /* Initializes data length. */ |
<> | 154:37f96f9d4de2 | 538 | curBuffDescrip->length = 0; |
<> | 154:37f96f9d4de2 | 539 | /* Sets the crc. */ |
<> | 154:37f96f9d4de2 | 540 | curBuffDescrip->control = ENET_BUFFDESCRIPTOR_TX_TRANMITCRC_MASK; |
<> | 154:37f96f9d4de2 | 541 | /* Sets the last buffer descriptor with the wrap flag. */ |
<> | 154:37f96f9d4de2 | 542 | if (count == txBdNumber - 1) |
<> | 154:37f96f9d4de2 | 543 | { |
<> | 154:37f96f9d4de2 | 544 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 545 | } |
<> | 154:37f96f9d4de2 | 546 | |
<> | 154:37f96f9d4de2 | 547 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 548 | /* Enable transmit interrupt for store the transmit timestamp. */ |
<> | 154:37f96f9d4de2 | 549 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_INTERRUPT_MASK; |
<> | 154:37f96f9d4de2 | 550 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 551 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 552 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 553 | } |
<> | 156:95d6b41a828b | 554 | |
<> | 154:37f96f9d4de2 | 555 | } |
<> | 154:37f96f9d4de2 | 556 | |
<> | 154:37f96f9d4de2 | 557 | static void ENET_SetRxBufferDescriptors(volatile enet_rx_bd_struct_t *rxBdStartAlign, |
<> | 154:37f96f9d4de2 | 558 | uint8_t *rxBuffStartAlign, |
<> | 154:37f96f9d4de2 | 559 | uint32_t rxBuffSizeAlign, |
<> | 154:37f96f9d4de2 | 560 | uint32_t rxBdNumber, |
<> | 154:37f96f9d4de2 | 561 | bool enableInterrupt) |
<> | 154:37f96f9d4de2 | 562 | { |
<> | 154:37f96f9d4de2 | 563 | assert(rxBdStartAlign); |
<> | 154:37f96f9d4de2 | 564 | assert(rxBuffStartAlign); |
<> | 154:37f96f9d4de2 | 565 | |
<> | 154:37f96f9d4de2 | 566 | volatile enet_rx_bd_struct_t *curBuffDescrip = rxBdStartAlign; |
<> | 154:37f96f9d4de2 | 567 | uint32_t count = 0; |
<> | 154:37f96f9d4de2 | 568 | |
<> | 154:37f96f9d4de2 | 569 | /* Initializes receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 570 | for (count = 0; count < rxBdNumber; count++) |
<> | 154:37f96f9d4de2 | 571 | { |
<> | 154:37f96f9d4de2 | 572 | /* Set data buffer and the length. */ |
<> | 154:37f96f9d4de2 | 573 | curBuffDescrip->buffer = (uint8_t *)(*((uint32_t *)(rxBuffStartAlign + count * 4))); |
<> | 154:37f96f9d4de2 | 574 | curBuffDescrip->length = 0; |
<> | 154:37f96f9d4de2 | 575 | |
<> | 154:37f96f9d4de2 | 576 | /* Initializes the buffer descriptors with empty bit. */ |
<> | 154:37f96f9d4de2 | 577 | curBuffDescrip->control = ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 578 | /* Sets the last buffer descriptor with the wrap flag. */ |
<> | 154:37f96f9d4de2 | 579 | if (count == rxBdNumber - 1) |
<> | 154:37f96f9d4de2 | 580 | { |
<> | 154:37f96f9d4de2 | 581 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 582 | } |
<> | 154:37f96f9d4de2 | 583 | |
<> | 154:37f96f9d4de2 | 584 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 585 | if (enableInterrupt) |
<> | 154:37f96f9d4de2 | 586 | { |
<> | 154:37f96f9d4de2 | 587 | /* Enable receive interrupt. */ |
<> | 154:37f96f9d4de2 | 588 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_RX_INTERRUPT_MASK; |
<> | 154:37f96f9d4de2 | 589 | } |
<> | 154:37f96f9d4de2 | 590 | else |
<> | 154:37f96f9d4de2 | 591 | { |
<> | 154:37f96f9d4de2 | 592 | curBuffDescrip->controlExtend1 = 0; |
<> | 154:37f96f9d4de2 | 593 | } |
<> | 154:37f96f9d4de2 | 594 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 595 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 596 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 597 | } |
<> | 154:37f96f9d4de2 | 598 | } |
<> | 154:37f96f9d4de2 | 599 | |
<> | 154:37f96f9d4de2 | 600 | void ENET_SetMII(ENET_Type *base, enet_mii_speed_t speed, enet_mii_duplex_t duplex) |
<> | 154:37f96f9d4de2 | 601 | { |
<> | 156:95d6b41a828b | 602 | uint32_t rcr = base->RCR; |
<> | 156:95d6b41a828b | 603 | uint32_t tcr = base->TCR; |
<> | 154:37f96f9d4de2 | 604 | /* Sets speed mode. */ |
<> | 154:37f96f9d4de2 | 605 | if (kENET_MiiSpeed10M == speed) |
<> | 154:37f96f9d4de2 | 606 | { |
<> | 154:37f96f9d4de2 | 607 | rcr |= ENET_RCR_RMII_10T_MASK; |
<> | 154:37f96f9d4de2 | 608 | } |
<> | 154:37f96f9d4de2 | 609 | else |
<> | 154:37f96f9d4de2 | 610 | { |
<> | 154:37f96f9d4de2 | 611 | rcr &= ~ENET_RCR_RMII_10T_MASK; |
<> | 154:37f96f9d4de2 | 612 | } |
<> | 154:37f96f9d4de2 | 613 | /* Set duplex mode. */ |
<> | 154:37f96f9d4de2 | 614 | if (duplex == kENET_MiiHalfDuplex) |
<> | 154:37f96f9d4de2 | 615 | { |
<> | 154:37f96f9d4de2 | 616 | rcr |= ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 617 | tcr &= ~ENET_TCR_FDEN_MASK; |
<> | 154:37f96f9d4de2 | 618 | } |
<> | 154:37f96f9d4de2 | 619 | else |
<> | 154:37f96f9d4de2 | 620 | { |
<> | 154:37f96f9d4de2 | 621 | rcr &= ~ENET_RCR_DRT_MASK; |
<> | 154:37f96f9d4de2 | 622 | tcr |= ENET_TCR_FDEN_MASK; |
<> | 154:37f96f9d4de2 | 623 | } |
<> | 154:37f96f9d4de2 | 624 | |
<> | 154:37f96f9d4de2 | 625 | base->RCR = rcr; |
<> | 154:37f96f9d4de2 | 626 | base->TCR = tcr; |
<> | 154:37f96f9d4de2 | 627 | } |
<> | 154:37f96f9d4de2 | 628 | |
<> | 154:37f96f9d4de2 | 629 | void ENET_SetMacAddr(ENET_Type *base, uint8_t *macAddr) |
<> | 154:37f96f9d4de2 | 630 | { |
<> | 154:37f96f9d4de2 | 631 | uint32_t address; |
<> | 154:37f96f9d4de2 | 632 | |
<> | 154:37f96f9d4de2 | 633 | /* Set physical address lower register. */ |
<> | 154:37f96f9d4de2 | 634 | address = (uint32_t)(((uint32_t)macAddr[0] << 24U) | ((uint32_t)macAddr[1] << 16U) | ((uint32_t)macAddr[2] << 8U) | |
<> | 154:37f96f9d4de2 | 635 | (uint32_t)macAddr[3]); |
<> | 154:37f96f9d4de2 | 636 | base->PALR = address; |
<> | 154:37f96f9d4de2 | 637 | /* Set physical address high register. */ |
<> | 154:37f96f9d4de2 | 638 | address = (uint32_t)(((uint32_t)macAddr[4] << 8U) | ((uint32_t)macAddr[5])); |
<> | 154:37f96f9d4de2 | 639 | base->PAUR = address << ENET_PAUR_PADDR2_SHIFT; |
<> | 154:37f96f9d4de2 | 640 | } |
<> | 154:37f96f9d4de2 | 641 | |
<> | 154:37f96f9d4de2 | 642 | void ENET_GetMacAddr(ENET_Type *base, uint8_t *macAddr) |
<> | 154:37f96f9d4de2 | 643 | { |
<> | 154:37f96f9d4de2 | 644 | assert(macAddr); |
<> | 154:37f96f9d4de2 | 645 | |
<> | 154:37f96f9d4de2 | 646 | uint32_t address; |
<> | 154:37f96f9d4de2 | 647 | |
<> | 154:37f96f9d4de2 | 648 | /* Get from physical address lower register. */ |
<> | 154:37f96f9d4de2 | 649 | address = base->PALR; |
<> | 154:37f96f9d4de2 | 650 | macAddr[0] = 0xFFU & (address >> 24U); |
<> | 154:37f96f9d4de2 | 651 | macAddr[1] = 0xFFU & (address >> 16U); |
<> | 154:37f96f9d4de2 | 652 | macAddr[2] = 0xFFU & (address >> 8U); |
<> | 154:37f96f9d4de2 | 653 | macAddr[3] = 0xFFU & address; |
<> | 154:37f96f9d4de2 | 654 | |
<> | 154:37f96f9d4de2 | 655 | /* Get from physical address high register. */ |
<> | 154:37f96f9d4de2 | 656 | address = (base->PAUR & ENET_PAUR_PADDR2_MASK) >> ENET_PAUR_PADDR2_SHIFT; |
<> | 154:37f96f9d4de2 | 657 | macAddr[4] = 0xFFU & (address >> 8U); |
<> | 154:37f96f9d4de2 | 658 | macAddr[5] = 0xFFU & address; |
<> | 154:37f96f9d4de2 | 659 | } |
<> | 154:37f96f9d4de2 | 660 | |
<> | 154:37f96f9d4de2 | 661 | void ENET_SetSMI(ENET_Type *base, uint32_t srcClock_Hz, bool isPreambleDisabled) |
<> | 154:37f96f9d4de2 | 662 | { |
<> | 154:37f96f9d4de2 | 663 | assert(srcClock_Hz); |
<> | 154:37f96f9d4de2 | 664 | |
<> | 154:37f96f9d4de2 | 665 | uint32_t clkCycle = 0; |
<> | 154:37f96f9d4de2 | 666 | uint32_t speed = 0; |
<> | 154:37f96f9d4de2 | 667 | uint32_t mscr = 0; |
<> | 154:37f96f9d4de2 | 668 | |
<> | 154:37f96f9d4de2 | 669 | /* Calculate the MII speed which controls the frequency of the MDC. */ |
<> | 154:37f96f9d4de2 | 670 | speed = srcClock_Hz / (2 * ENET_MDC_FREQUENCY); |
<> | 154:37f96f9d4de2 | 671 | /* Calculate the hold time on the MDIO output. */ |
<> | 154:37f96f9d4de2 | 672 | clkCycle = (10 + ENET_NANOSECOND_ONE_SECOND / srcClock_Hz - 1) / (ENET_NANOSECOND_ONE_SECOND / srcClock_Hz) - 1; |
<> | 154:37f96f9d4de2 | 673 | /* Build the configuration for MDC/MDIO control. */ |
<> | 154:37f96f9d4de2 | 674 | mscr = ENET_MSCR_MII_SPEED(speed) | ENET_MSCR_DIS_PRE(isPreambleDisabled) | ENET_MSCR_HOLDTIME(clkCycle); |
<> | 154:37f96f9d4de2 | 675 | base->MSCR = mscr; |
<> | 154:37f96f9d4de2 | 676 | } |
<> | 154:37f96f9d4de2 | 677 | |
<> | 154:37f96f9d4de2 | 678 | void ENET_StartSMIWrite(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_write_t operation, uint32_t data) |
<> | 154:37f96f9d4de2 | 679 | { |
<> | 154:37f96f9d4de2 | 680 | uint32_t mmfr = 0; |
<> | 154:37f96f9d4de2 | 681 | |
<> | 154:37f96f9d4de2 | 682 | /* Build MII write command. */ |
<> | 154:37f96f9d4de2 | 683 | mmfr = ENET_MMFR_ST(1) | ENET_MMFR_OP(operation) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(phyReg) | ENET_MMFR_TA(2) | |
<> | 154:37f96f9d4de2 | 684 | (data & 0xFFFF); |
<> | 154:37f96f9d4de2 | 685 | base->MMFR = mmfr; |
<> | 154:37f96f9d4de2 | 686 | } |
<> | 154:37f96f9d4de2 | 687 | |
<> | 154:37f96f9d4de2 | 688 | void ENET_StartSMIRead(ENET_Type *base, uint32_t phyAddr, uint32_t phyReg, enet_mii_read_t operation) |
<> | 154:37f96f9d4de2 | 689 | { |
<> | 154:37f96f9d4de2 | 690 | uint32_t mmfr = 0; |
<> | 154:37f96f9d4de2 | 691 | |
<> | 154:37f96f9d4de2 | 692 | /* Build MII read command. */ |
<> | 154:37f96f9d4de2 | 693 | mmfr = ENET_MMFR_ST(1) | ENET_MMFR_OP(operation) | ENET_MMFR_PA(phyAddr) | ENET_MMFR_RA(phyReg) | ENET_MMFR_TA(2); |
<> | 154:37f96f9d4de2 | 694 | base->MMFR = mmfr; |
<> | 154:37f96f9d4de2 | 695 | } |
<> | 154:37f96f9d4de2 | 696 | |
<> | 154:37f96f9d4de2 | 697 | void ENET_GetRxErrBeforeReadFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) |
<> | 154:37f96f9d4de2 | 698 | { |
<> | 154:37f96f9d4de2 | 699 | assert(handle); |
<> | 154:37f96f9d4de2 | 700 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 701 | assert(eErrorStatic); |
<> | 154:37f96f9d4de2 | 702 | |
<> | 154:37f96f9d4de2 | 703 | uint16_t control = 0; |
<> | 154:37f96f9d4de2 | 704 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 705 | |
<> | 154:37f96f9d4de2 | 706 | do |
<> | 154:37f96f9d4de2 | 707 | { |
<> | 154:37f96f9d4de2 | 708 | /* The last buffer descriptor of a frame. */ |
<> | 154:37f96f9d4de2 | 709 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 710 | { |
<> | 154:37f96f9d4de2 | 711 | control = curBuffDescrip->control; |
<> | 154:37f96f9d4de2 | 712 | if (control & ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK) |
<> | 154:37f96f9d4de2 | 713 | { |
<> | 154:37f96f9d4de2 | 714 | /* The receive truncate error. */ |
<> | 154:37f96f9d4de2 | 715 | eErrorStatic->statsRxTruncateErr++; |
<> | 154:37f96f9d4de2 | 716 | } |
<> | 154:37f96f9d4de2 | 717 | if (control & ENET_BUFFDESCRIPTOR_RX_OVERRUN_MASK) |
<> | 154:37f96f9d4de2 | 718 | { |
<> | 154:37f96f9d4de2 | 719 | /* The receive over run error. */ |
<> | 154:37f96f9d4de2 | 720 | eErrorStatic->statsRxOverRunErr++; |
<> | 154:37f96f9d4de2 | 721 | } |
<> | 154:37f96f9d4de2 | 722 | if (control & ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK) |
<> | 154:37f96f9d4de2 | 723 | { |
<> | 154:37f96f9d4de2 | 724 | /* The receive length violation error. */ |
<> | 154:37f96f9d4de2 | 725 | eErrorStatic->statsRxLenGreaterErr++; |
<> | 154:37f96f9d4de2 | 726 | } |
<> | 154:37f96f9d4de2 | 727 | if (control & ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK) |
<> | 154:37f96f9d4de2 | 728 | { |
<> | 154:37f96f9d4de2 | 729 | /* The receive alignment error. */ |
<> | 154:37f96f9d4de2 | 730 | eErrorStatic->statsRxAlignErr++; |
<> | 154:37f96f9d4de2 | 731 | } |
<> | 154:37f96f9d4de2 | 732 | if (control & ENET_BUFFDESCRIPTOR_RX_CRC_MASK) |
<> | 154:37f96f9d4de2 | 733 | { |
<> | 154:37f96f9d4de2 | 734 | /* The receive CRC error. */ |
<> | 154:37f96f9d4de2 | 735 | eErrorStatic->statsRxFcsErr++; |
<> | 154:37f96f9d4de2 | 736 | } |
<> | 154:37f96f9d4de2 | 737 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 738 | uint16_t controlExt = curBuffDescrip->controlExtend1; |
<> | 154:37f96f9d4de2 | 739 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_MACERR_MASK) |
<> | 154:37f96f9d4de2 | 740 | { |
<> | 154:37f96f9d4de2 | 741 | /* The MAC error. */ |
<> | 154:37f96f9d4de2 | 742 | eErrorStatic->statsRxMacErr++; |
<> | 154:37f96f9d4de2 | 743 | } |
<> | 154:37f96f9d4de2 | 744 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_PHYERR_MASK) |
<> | 154:37f96f9d4de2 | 745 | { |
<> | 154:37f96f9d4de2 | 746 | /* The PHY error. */ |
<> | 154:37f96f9d4de2 | 747 | eErrorStatic->statsRxPhyErr++; |
<> | 154:37f96f9d4de2 | 748 | } |
<> | 154:37f96f9d4de2 | 749 | if (controlExt & ENET_BUFFDESCRIPTOR_RX_COLLISION_MASK) |
<> | 154:37f96f9d4de2 | 750 | { |
<> | 154:37f96f9d4de2 | 751 | /* The receive collision error. */ |
<> | 154:37f96f9d4de2 | 752 | eErrorStatic->statsRxCollisionErr++; |
<> | 154:37f96f9d4de2 | 753 | } |
<> | 154:37f96f9d4de2 | 754 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 755 | |
<> | 154:37f96f9d4de2 | 756 | break; |
<> | 154:37f96f9d4de2 | 757 | } |
<> | 154:37f96f9d4de2 | 758 | |
<> | 154:37f96f9d4de2 | 759 | /* Increase the buffer descriptor, if it is the last one, increase to first one of the ring buffer. */ |
<> | 154:37f96f9d4de2 | 760 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 761 | { |
<> | 154:37f96f9d4de2 | 762 | curBuffDescrip = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 763 | } |
<> | 154:37f96f9d4de2 | 764 | else |
<> | 154:37f96f9d4de2 | 765 | { |
<> | 154:37f96f9d4de2 | 766 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 767 | } |
<> | 154:37f96f9d4de2 | 768 | |
<> | 154:37f96f9d4de2 | 769 | } while (curBuffDescrip != handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 770 | } |
<> | 154:37f96f9d4de2 | 771 | |
<> | 154:37f96f9d4de2 | 772 | status_t ENET_GetRxFrameSize(enet_handle_t *handle, uint32_t *length) |
<> | 154:37f96f9d4de2 | 773 | { |
<> | 154:37f96f9d4de2 | 774 | assert(handle); |
<> | 154:37f96f9d4de2 | 775 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 776 | assert(length); |
<> | 154:37f96f9d4de2 | 777 | |
<> | 154:37f96f9d4de2 | 778 | /* Reset the length to zero. */ |
<> | 154:37f96f9d4de2 | 779 | *length = 0; |
<> | 154:37f96f9d4de2 | 780 | |
<> | 154:37f96f9d4de2 | 781 | uint16_t validLastMask = ENET_BUFFDESCRIPTOR_RX_LAST_MASK | ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 782 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 783 | |
<> | 154:37f96f9d4de2 | 784 | /* Check the current buffer descriptor's empty flag. if empty means there is no frame received. */ |
<> | 154:37f96f9d4de2 | 785 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) |
<> | 154:37f96f9d4de2 | 786 | { |
<> | 154:37f96f9d4de2 | 787 | return kStatus_ENET_RxFrameEmpty; |
<> | 154:37f96f9d4de2 | 788 | } |
<> | 154:37f96f9d4de2 | 789 | |
<> | 154:37f96f9d4de2 | 790 | do |
<> | 154:37f96f9d4de2 | 791 | { |
<> | 154:37f96f9d4de2 | 792 | /* Find the last buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 793 | if ((curBuffDescrip->control & validLastMask) == ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 794 | { |
<> | 154:37f96f9d4de2 | 795 | /* The last buffer descriptor in the frame check the status of the received frame. */ |
<> | 154:37f96f9d4de2 | 796 | if ((curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_ERR_MASK) |
<> | 154:37f96f9d4de2 | 797 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 798 | || (curBuffDescrip->controlExtend1 & ENET_BUFFDESCRIPTOR_RX_EXT_ERR_MASK) |
<> | 154:37f96f9d4de2 | 799 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 800 | ) |
<> | 154:37f96f9d4de2 | 801 | { |
<> | 154:37f96f9d4de2 | 802 | return kStatus_ENET_RxFrameError; |
<> | 154:37f96f9d4de2 | 803 | } |
<> | 154:37f96f9d4de2 | 804 | /* FCS is removed by MAC. */ |
<> | 154:37f96f9d4de2 | 805 | *length = curBuffDescrip->length; |
<> | 154:37f96f9d4de2 | 806 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 807 | } |
<> | 154:37f96f9d4de2 | 808 | /* Increase the buffer descriptor, if it is the last one, increase to first one of the ring buffer. */ |
<> | 154:37f96f9d4de2 | 809 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 810 | { |
<> | 154:37f96f9d4de2 | 811 | curBuffDescrip = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 812 | } |
<> | 154:37f96f9d4de2 | 813 | else |
<> | 154:37f96f9d4de2 | 814 | { |
<> | 154:37f96f9d4de2 | 815 | curBuffDescrip++; |
<> | 154:37f96f9d4de2 | 816 | } |
<> | 154:37f96f9d4de2 | 817 | |
<> | 154:37f96f9d4de2 | 818 | } while (curBuffDescrip != handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 819 | |
<> | 154:37f96f9d4de2 | 820 | /* The frame is on processing - set to empty status to make application to receive it next time. */ |
<> | 154:37f96f9d4de2 | 821 | return kStatus_ENET_RxFrameEmpty; |
<> | 154:37f96f9d4de2 | 822 | } |
<> | 154:37f96f9d4de2 | 823 | |
<> | 154:37f96f9d4de2 | 824 | status_t ENET_ReadFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) |
<> | 154:37f96f9d4de2 | 825 | { |
<> | 154:37f96f9d4de2 | 826 | assert(handle); |
<> | 154:37f96f9d4de2 | 827 | assert(handle->rxBdCurrent); |
<> | 154:37f96f9d4de2 | 828 | |
<> | 154:37f96f9d4de2 | 829 | uint32_t len = 0; |
<> | 154:37f96f9d4de2 | 830 | uint32_t offset = 0; |
<> | 154:37f96f9d4de2 | 831 | uint16_t control; |
<> | 154:37f96f9d4de2 | 832 | bool isLastBuff = false; |
<> | 154:37f96f9d4de2 | 833 | volatile enet_rx_bd_struct_t *curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 834 | status_t result = kStatus_Success; |
<> | 154:37f96f9d4de2 | 835 | |
<> | 154:37f96f9d4de2 | 836 | /* For data-NULL input, only update the buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 837 | if (!data) |
<> | 154:37f96f9d4de2 | 838 | { |
<> | 154:37f96f9d4de2 | 839 | do |
<> | 154:37f96f9d4de2 | 840 | { |
<> | 154:37f96f9d4de2 | 841 | /* Update the control flag. */ |
<> | 154:37f96f9d4de2 | 842 | control = handle->rxBdCurrent->control; |
<> | 154:37f96f9d4de2 | 843 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 844 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 845 | |
<> | 154:37f96f9d4de2 | 846 | /* Find the last buffer descriptor for the frame. */ |
<> | 154:37f96f9d4de2 | 847 | if (control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 848 | { |
<> | 154:37f96f9d4de2 | 849 | break; |
<> | 154:37f96f9d4de2 | 850 | } |
<> | 154:37f96f9d4de2 | 851 | |
<> | 154:37f96f9d4de2 | 852 | } while (handle->rxBdCurrent != curBuffDescrip); |
<> | 154:37f96f9d4de2 | 853 | |
<> | 154:37f96f9d4de2 | 854 | return result; |
<> | 154:37f96f9d4de2 | 855 | } |
<> | 154:37f96f9d4de2 | 856 | else |
<> | 154:37f96f9d4de2 | 857 | { |
<> | 154:37f96f9d4de2 | 858 | /* A frame on one buffer or several receive buffers are both considered. */ |
<> | 154:37f96f9d4de2 | 859 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 860 | enet_ptp_time_data_t ptpTimestamp; |
<> | 154:37f96f9d4de2 | 861 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 862 | |
<> | 154:37f96f9d4de2 | 863 | /* Parse the PTP message according to the header message. */ |
<> | 154:37f96f9d4de2 | 864 | isPtpEventMessage = ENET_Ptp1588ParseFrame(curBuffDescrip->buffer, &ptpTimestamp, false); |
<> | 154:37f96f9d4de2 | 865 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 866 | |
<> | 154:37f96f9d4de2 | 867 | while (!isLastBuff) |
<> | 154:37f96f9d4de2 | 868 | { |
<> | 154:37f96f9d4de2 | 869 | /* The last buffer descriptor of a frame. */ |
<> | 154:37f96f9d4de2 | 870 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_RX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 871 | { |
<> | 154:37f96f9d4de2 | 872 | /* This is a valid frame. */ |
<> | 154:37f96f9d4de2 | 873 | isLastBuff = true; |
<> | 154:37f96f9d4de2 | 874 | if (length == curBuffDescrip->length) |
<> | 154:37f96f9d4de2 | 875 | { |
<> | 154:37f96f9d4de2 | 876 | /* Copy the frame to user's buffer without FCS. */ |
<> | 154:37f96f9d4de2 | 877 | len = curBuffDescrip->length - offset; |
<> | 154:37f96f9d4de2 | 878 | memcpy(data + offset, curBuffDescrip->buffer, len); |
<> | 154:37f96f9d4de2 | 879 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 880 | /* Store the PTP 1588 timestamp for received PTP event frame. */ |
<> | 154:37f96f9d4de2 | 881 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 882 | { |
<> | 154:37f96f9d4de2 | 883 | /* Set the timestamp to the timestamp ring. */ |
<> | 154:37f96f9d4de2 | 884 | ptpTimestamp.timeStamp.nanosecond = curBuffDescrip->timestamp; |
<> | 154:37f96f9d4de2 | 885 | result = ENET_StoreRxFrameTime(base, handle, &ptpTimestamp); |
<> | 154:37f96f9d4de2 | 886 | } |
<> | 154:37f96f9d4de2 | 887 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 888 | |
<> | 154:37f96f9d4de2 | 889 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 890 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 891 | return result; |
<> | 154:37f96f9d4de2 | 892 | } |
<> | 154:37f96f9d4de2 | 893 | else |
<> | 154:37f96f9d4de2 | 894 | { |
<> | 154:37f96f9d4de2 | 895 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 896 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 897 | } |
<> | 154:37f96f9d4de2 | 898 | } |
<> | 154:37f96f9d4de2 | 899 | else |
<> | 154:37f96f9d4de2 | 900 | { |
<> | 154:37f96f9d4de2 | 901 | /* Store a frame on several buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 902 | isLastBuff = false; |
<> | 154:37f96f9d4de2 | 903 | /* Length check. */ |
<> | 154:37f96f9d4de2 | 904 | if (offset >= length) |
<> | 154:37f96f9d4de2 | 905 | { |
<> | 154:37f96f9d4de2 | 906 | break; |
<> | 154:37f96f9d4de2 | 907 | } |
<> | 154:37f96f9d4de2 | 908 | memcpy(data + offset, curBuffDescrip->buffer, handle->rxBuffSizeAlign); |
<> | 154:37f96f9d4de2 | 909 | offset += handle->rxBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 910 | |
<> | 154:37f96f9d4de2 | 911 | /* Updates the receive buffer descriptors. */ |
<> | 154:37f96f9d4de2 | 912 | ENET_UpdateReadBuffers(base, handle); |
<> | 154:37f96f9d4de2 | 913 | } |
<> | 154:37f96f9d4de2 | 914 | |
<> | 154:37f96f9d4de2 | 915 | /* Get the current buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 916 | curBuffDescrip = handle->rxBdCurrent; |
<> | 154:37f96f9d4de2 | 917 | } |
<> | 154:37f96f9d4de2 | 918 | } |
<> | 154:37f96f9d4de2 | 919 | |
<> | 154:37f96f9d4de2 | 920 | return kStatus_ENET_RxFrameFail; |
<> | 154:37f96f9d4de2 | 921 | } |
<> | 154:37f96f9d4de2 | 922 | |
<> | 154:37f96f9d4de2 | 923 | static void ENET_UpdateReadBuffers(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 924 | { |
<> | 154:37f96f9d4de2 | 925 | assert(handle); |
<> | 154:37f96f9d4de2 | 926 | |
<> | 154:37f96f9d4de2 | 927 | /* Clears status. */ |
<> | 154:37f96f9d4de2 | 928 | handle->rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; |
<> | 154:37f96f9d4de2 | 929 | /* Sets the receive buffer descriptor with the empty flag. */ |
<> | 154:37f96f9d4de2 | 930 | handle->rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; |
<> | 154:37f96f9d4de2 | 931 | |
<> | 154:37f96f9d4de2 | 932 | /* Increase current buffer descriptor to the next one. */ |
<> | 154:37f96f9d4de2 | 933 | if (handle->rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 934 | { |
<> | 154:37f96f9d4de2 | 935 | handle->rxBdCurrent = handle->rxBdBase; |
<> | 154:37f96f9d4de2 | 936 | } |
<> | 154:37f96f9d4de2 | 937 | else |
<> | 154:37f96f9d4de2 | 938 | { |
<> | 154:37f96f9d4de2 | 939 | handle->rxBdCurrent++; |
<> | 154:37f96f9d4de2 | 940 | } |
<> | 154:37f96f9d4de2 | 941 | |
<> | 154:37f96f9d4de2 | 942 | /* Actives the receive buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 943 | base->RDAR = ENET_RDAR_RDAR_MASK; |
<> | 154:37f96f9d4de2 | 944 | } |
<> | 154:37f96f9d4de2 | 945 | |
<> | 154:37f96f9d4de2 | 946 | status_t ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, uint8_t *data, uint32_t length) |
<> | 154:37f96f9d4de2 | 947 | { |
<> | 154:37f96f9d4de2 | 948 | assert(handle); |
<> | 154:37f96f9d4de2 | 949 | assert(handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 950 | assert(data); |
<> | 154:37f96f9d4de2 | 951 | assert(length <= (ENET_FRAME_MAX_VALNFRAMELEN - 4)); |
<> | 154:37f96f9d4de2 | 952 | |
<> | 154:37f96f9d4de2 | 953 | volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdCurrent; |
<> | 154:37f96f9d4de2 | 954 | uint32_t len = 0; |
<> | 154:37f96f9d4de2 | 955 | uint32_t sizeleft = 0; |
<> | 154:37f96f9d4de2 | 956 | |
<> | 154:37f96f9d4de2 | 957 | /* Check if the transmit buffer is ready. */ |
<> | 154:37f96f9d4de2 | 958 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 959 | { |
<> | 154:37f96f9d4de2 | 960 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 961 | } |
<> | 154:37f96f9d4de2 | 962 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 963 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 964 | /* Check PTP message with the PTP header. */ |
<> | 154:37f96f9d4de2 | 965 | isPtpEventMessage = ENET_Ptp1588ParseFrame(data, NULL, true); |
<> | 154:37f96f9d4de2 | 966 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 967 | /* One transmit buffer is enough for one frame. */ |
<> | 154:37f96f9d4de2 | 968 | if (handle->txBuffSizeAlign >= length) |
<> | 154:37f96f9d4de2 | 969 | { |
<> | 154:37f96f9d4de2 | 970 | /* Copy data to the buffer for uDMA transfer. */ |
<> | 154:37f96f9d4de2 | 971 | memcpy(curBuffDescrip->buffer, data, length); |
<> | 154:37f96f9d4de2 | 972 | /* Set data length. */ |
<> | 154:37f96f9d4de2 | 973 | curBuffDescrip->length = length; |
<> | 154:37f96f9d4de2 | 974 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 975 | /* For enable the timestamp. */ |
<> | 154:37f96f9d4de2 | 976 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 977 | { |
<> | 154:37f96f9d4de2 | 978 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 979 | } |
<> | 154:37f96f9d4de2 | 980 | else |
<> | 154:37f96f9d4de2 | 981 | { |
<> | 154:37f96f9d4de2 | 982 | curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 983 | } |
<> | 154:37f96f9d4de2 | 984 | |
<> | 154:37f96f9d4de2 | 985 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 986 | curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); |
<> | 154:37f96f9d4de2 | 987 | |
<> | 154:37f96f9d4de2 | 988 | /* Increase the buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 989 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 990 | { |
<> | 154:37f96f9d4de2 | 991 | handle->txBdCurrent = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 992 | } |
<> | 154:37f96f9d4de2 | 993 | else |
<> | 154:37f96f9d4de2 | 994 | { |
<> | 154:37f96f9d4de2 | 995 | handle->txBdCurrent++; |
<> | 154:37f96f9d4de2 | 996 | } |
<> | 154:37f96f9d4de2 | 997 | |
<> | 154:37f96f9d4de2 | 998 | /* Active the transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 999 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 1000 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1001 | } |
<> | 154:37f96f9d4de2 | 1002 | else |
<> | 154:37f96f9d4de2 | 1003 | { |
<> | 154:37f96f9d4de2 | 1004 | /* One frame requires more than one transmit buffers. */ |
<> | 154:37f96f9d4de2 | 1005 | do |
<> | 154:37f96f9d4de2 | 1006 | { |
<> | 154:37f96f9d4de2 | 1007 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1008 | /* For enable the timestamp. */ |
<> | 154:37f96f9d4de2 | 1009 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 1010 | { |
<> | 154:37f96f9d4de2 | 1011 | curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 1012 | } |
<> | 154:37f96f9d4de2 | 1013 | else |
<> | 154:37f96f9d4de2 | 1014 | { |
<> | 154:37f96f9d4de2 | 1015 | curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; |
<> | 154:37f96f9d4de2 | 1016 | } |
<> | 154:37f96f9d4de2 | 1017 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1018 | |
<> | 154:37f96f9d4de2 | 1019 | /* Increase the buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 1020 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1021 | { |
<> | 154:37f96f9d4de2 | 1022 | handle->txBdCurrent = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1023 | } |
<> | 154:37f96f9d4de2 | 1024 | else |
<> | 154:37f96f9d4de2 | 1025 | { |
<> | 154:37f96f9d4de2 | 1026 | handle->txBdCurrent++; |
<> | 154:37f96f9d4de2 | 1027 | } |
<> | 154:37f96f9d4de2 | 1028 | /* update the size left to be transmit. */ |
<> | 154:37f96f9d4de2 | 1029 | sizeleft = length - len; |
<> | 154:37f96f9d4de2 | 1030 | if (sizeleft > handle->txBuffSizeAlign) |
<> | 154:37f96f9d4de2 | 1031 | { |
<> | 154:37f96f9d4de2 | 1032 | /* Data copy. */ |
<> | 154:37f96f9d4de2 | 1033 | memcpy(curBuffDescrip->buffer, data + len, handle->txBuffSizeAlign); |
<> | 154:37f96f9d4de2 | 1034 | /* Data length update. */ |
<> | 154:37f96f9d4de2 | 1035 | curBuffDescrip->length = handle->txBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 1036 | len += handle->txBuffSizeAlign; |
<> | 154:37f96f9d4de2 | 1037 | /* Sets the control flag. */ |
<> | 154:37f96f9d4de2 | 1038 | curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; |
<> | 154:37f96f9d4de2 | 1039 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; |
<> | 154:37f96f9d4de2 | 1040 | /* Active the transmit buffer descriptor*/ |
<> | 154:37f96f9d4de2 | 1041 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 1042 | } |
<> | 154:37f96f9d4de2 | 1043 | else |
<> | 154:37f96f9d4de2 | 1044 | { |
<> | 154:37f96f9d4de2 | 1045 | memcpy(curBuffDescrip->buffer, data + len, sizeleft); |
<> | 154:37f96f9d4de2 | 1046 | curBuffDescrip->length = sizeleft; |
<> | 154:37f96f9d4de2 | 1047 | /* Set Last buffer wrap flag. */ |
<> | 154:37f96f9d4de2 | 1048 | curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK; |
<> | 154:37f96f9d4de2 | 1049 | /* Active the transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1050 | base->TDAR = ENET_TDAR_TDAR_MASK; |
<> | 154:37f96f9d4de2 | 1051 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1052 | } |
<> | 154:37f96f9d4de2 | 1053 | |
<> | 154:37f96f9d4de2 | 1054 | /* Get the current buffer descriptor address. */ |
<> | 154:37f96f9d4de2 | 1055 | curBuffDescrip = handle->txBdCurrent; |
<> | 154:37f96f9d4de2 | 1056 | |
<> | 154:37f96f9d4de2 | 1057 | } while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); |
<> | 154:37f96f9d4de2 | 1058 | |
<> | 154:37f96f9d4de2 | 1059 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1060 | } |
<> | 154:37f96f9d4de2 | 1061 | } |
<> | 154:37f96f9d4de2 | 1062 | |
<> | 154:37f96f9d4de2 | 1063 | void ENET_AddMulticastGroup(ENET_Type *base, uint8_t *address) |
<> | 154:37f96f9d4de2 | 1064 | { |
<> | 154:37f96f9d4de2 | 1065 | assert(address); |
<> | 154:37f96f9d4de2 | 1066 | |
<> | 154:37f96f9d4de2 | 1067 | uint32_t crc = 0xFFFFFFFFU; |
<> | 154:37f96f9d4de2 | 1068 | uint32_t count1 = 0; |
<> | 154:37f96f9d4de2 | 1069 | uint32_t count2 = 0; |
<> | 154:37f96f9d4de2 | 1070 | |
<> | 154:37f96f9d4de2 | 1071 | /* Calculates the CRC-32 polynomial on the multicast group address. */ |
<> | 154:37f96f9d4de2 | 1072 | for (count1 = 0; count1 < ENET_FRAME_MACLEN; count1++) |
<> | 154:37f96f9d4de2 | 1073 | { |
<> | 154:37f96f9d4de2 | 1074 | uint8_t c = address[count1]; |
<> | 154:37f96f9d4de2 | 1075 | for (count2 = 0; count2 < 0x08U; count2++) |
<> | 154:37f96f9d4de2 | 1076 | { |
<> | 154:37f96f9d4de2 | 1077 | if ((c ^ crc) & 1U) |
<> | 154:37f96f9d4de2 | 1078 | { |
<> | 154:37f96f9d4de2 | 1079 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1080 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1081 | crc ^= 0xEDB88320U; |
<> | 154:37f96f9d4de2 | 1082 | } |
<> | 154:37f96f9d4de2 | 1083 | else |
<> | 154:37f96f9d4de2 | 1084 | { |
<> | 154:37f96f9d4de2 | 1085 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1086 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1087 | } |
<> | 154:37f96f9d4de2 | 1088 | } |
<> | 154:37f96f9d4de2 | 1089 | } |
<> | 154:37f96f9d4de2 | 1090 | |
<> | 154:37f96f9d4de2 | 1091 | /* Enable a multicast group address. */ |
<> | 154:37f96f9d4de2 | 1092 | if (!((crc >> 0x1FU) & 1U)) |
<> | 154:37f96f9d4de2 | 1093 | { |
<> | 154:37f96f9d4de2 | 1094 | base->GALR |= 1U << ((crc >> 0x1AU) & 0x1FU); |
<> | 154:37f96f9d4de2 | 1095 | } |
<> | 154:37f96f9d4de2 | 1096 | else |
<> | 154:37f96f9d4de2 | 1097 | { |
<> | 154:37f96f9d4de2 | 1098 | base->GAUR |= 1U << ((crc >> 0x1AU) & 0x1FU); |
<> | 154:37f96f9d4de2 | 1099 | } |
<> | 154:37f96f9d4de2 | 1100 | } |
<> | 154:37f96f9d4de2 | 1101 | |
<> | 154:37f96f9d4de2 | 1102 | void ENET_LeaveMulticastGroup(ENET_Type *base, uint8_t *address) |
<> | 154:37f96f9d4de2 | 1103 | { |
<> | 154:37f96f9d4de2 | 1104 | assert(address); |
<> | 154:37f96f9d4de2 | 1105 | |
<> | 154:37f96f9d4de2 | 1106 | uint32_t crc = 0xFFFFFFFFU; |
<> | 154:37f96f9d4de2 | 1107 | uint32_t count1 = 0; |
<> | 154:37f96f9d4de2 | 1108 | uint32_t count2 = 0; |
<> | 154:37f96f9d4de2 | 1109 | |
<> | 154:37f96f9d4de2 | 1110 | /* Calculates the CRC-32 polynomial on the multicast group address. */ |
<> | 154:37f96f9d4de2 | 1111 | for (count1 = 0; count1 < ENET_FRAME_MACLEN; count1++) |
<> | 154:37f96f9d4de2 | 1112 | { |
<> | 154:37f96f9d4de2 | 1113 | uint8_t c = address[count1]; |
<> | 154:37f96f9d4de2 | 1114 | for (count2 = 0; count2 < 0x08U; count2++) |
<> | 154:37f96f9d4de2 | 1115 | { |
<> | 154:37f96f9d4de2 | 1116 | if ((c ^ crc) & 1U) |
<> | 154:37f96f9d4de2 | 1117 | { |
<> | 154:37f96f9d4de2 | 1118 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1119 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1120 | crc ^= 0xEDB88320U; |
<> | 154:37f96f9d4de2 | 1121 | } |
<> | 154:37f96f9d4de2 | 1122 | else |
<> | 154:37f96f9d4de2 | 1123 | { |
<> | 154:37f96f9d4de2 | 1124 | crc >>= 1U; |
<> | 154:37f96f9d4de2 | 1125 | c >>= 1U; |
<> | 154:37f96f9d4de2 | 1126 | } |
<> | 154:37f96f9d4de2 | 1127 | } |
<> | 154:37f96f9d4de2 | 1128 | } |
<> | 154:37f96f9d4de2 | 1129 | |
<> | 154:37f96f9d4de2 | 1130 | /* Set the hash table. */ |
<> | 154:37f96f9d4de2 | 1131 | if (!((crc >> 0x1FU) & 1U)) |
<> | 154:37f96f9d4de2 | 1132 | { |
<> | 154:37f96f9d4de2 | 1133 | base->GALR &= ~(1U << ((crc >> 0x1AU) & 0x1FU)); |
<> | 154:37f96f9d4de2 | 1134 | } |
<> | 154:37f96f9d4de2 | 1135 | else |
<> | 154:37f96f9d4de2 | 1136 | { |
<> | 154:37f96f9d4de2 | 1137 | base->GAUR &= ~(1U << ((crc >> 0x1AU) & 0x1FU)); |
<> | 154:37f96f9d4de2 | 1138 | } |
<> | 154:37f96f9d4de2 | 1139 | } |
<> | 154:37f96f9d4de2 | 1140 | |
<> | 154:37f96f9d4de2 | 1141 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1142 | status_t ENET_GetTxErrAfterSendFrame(enet_handle_t *handle, enet_data_error_stats_t *eErrorStatic) |
<> | 154:37f96f9d4de2 | 1143 | { |
<> | 154:37f96f9d4de2 | 1144 | assert(handle); |
<> | 154:37f96f9d4de2 | 1145 | assert(eErrorStatic); |
<> | 154:37f96f9d4de2 | 1146 | |
<> | 154:37f96f9d4de2 | 1147 | uint16_t control = 0; |
<> | 154:37f96f9d4de2 | 1148 | uint16_t controlExt = 0; |
<> | 154:37f96f9d4de2 | 1149 | |
<> | 154:37f96f9d4de2 | 1150 | do |
<> | 154:37f96f9d4de2 | 1151 | { |
<> | 154:37f96f9d4de2 | 1152 | /* Get the current dirty transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1153 | control = handle->txBdDirtyStatic->control; |
<> | 154:37f96f9d4de2 | 1154 | controlExt = handle->txBdDirtyStatic->controlExtend0; |
<> | 154:37f96f9d4de2 | 1155 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1156 | if (control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1157 | { |
<> | 154:37f96f9d4de2 | 1158 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1159 | } |
<> | 154:37f96f9d4de2 | 1160 | /* Increase the transmit dirty static pointer. */ |
<> | 154:37f96f9d4de2 | 1161 | if (handle->txBdDirtyStatic->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1162 | { |
<> | 154:37f96f9d4de2 | 1163 | handle->txBdDirtyStatic = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1164 | } |
<> | 154:37f96f9d4de2 | 1165 | else |
<> | 154:37f96f9d4de2 | 1166 | { |
<> | 154:37f96f9d4de2 | 1167 | handle->txBdDirtyStatic++; |
<> | 154:37f96f9d4de2 | 1168 | } |
<> | 154:37f96f9d4de2 | 1169 | |
<> | 154:37f96f9d4de2 | 1170 | /* If the transmit buffer descriptor is ready and the last buffer descriptor, store packet statistic. */ |
<> | 154:37f96f9d4de2 | 1171 | if (control & ENET_BUFFDESCRIPTOR_TX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 1172 | { |
<> | 154:37f96f9d4de2 | 1173 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_ERR_MASK) |
<> | 154:37f96f9d4de2 | 1174 | { |
<> | 154:37f96f9d4de2 | 1175 | /* Transmit error. */ |
<> | 154:37f96f9d4de2 | 1176 | eErrorStatic->statsTxErr++; |
<> | 154:37f96f9d4de2 | 1177 | } |
<> | 154:37f96f9d4de2 | 1178 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_EXCCOLLISIONERR_MASK) |
<> | 154:37f96f9d4de2 | 1179 | { |
<> | 154:37f96f9d4de2 | 1180 | /* Transmit excess collision error. */ |
<> | 154:37f96f9d4de2 | 1181 | eErrorStatic->statsTxExcessCollisionErr++; |
<> | 154:37f96f9d4de2 | 1182 | } |
<> | 154:37f96f9d4de2 | 1183 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_LATECOLLISIONERR_MASK) |
<> | 154:37f96f9d4de2 | 1184 | { |
<> | 154:37f96f9d4de2 | 1185 | /* Transmit late collision error. */ |
<> | 154:37f96f9d4de2 | 1186 | eErrorStatic->statsTxLateCollisionErr++; |
<> | 154:37f96f9d4de2 | 1187 | } |
<> | 154:37f96f9d4de2 | 1188 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_UNDERFLOWERR_MASK) |
<> | 154:37f96f9d4de2 | 1189 | { |
<> | 154:37f96f9d4de2 | 1190 | /* Transmit under flow error. */ |
<> | 154:37f96f9d4de2 | 1191 | eErrorStatic->statsTxUnderFlowErr++; |
<> | 154:37f96f9d4de2 | 1192 | } |
<> | 154:37f96f9d4de2 | 1193 | if (controlExt & ENET_BUFFDESCRIPTOR_TX_OVERFLOWERR_MASK) |
<> | 154:37f96f9d4de2 | 1194 | { |
<> | 154:37f96f9d4de2 | 1195 | /* Transmit over flow error. */ |
<> | 154:37f96f9d4de2 | 1196 | eErrorStatic->statsTxOverFlowErr++; |
<> | 154:37f96f9d4de2 | 1197 | } |
<> | 154:37f96f9d4de2 | 1198 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1199 | } |
<> | 154:37f96f9d4de2 | 1200 | |
<> | 154:37f96f9d4de2 | 1201 | } while (handle->txBdDirtyStatic != handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 1202 | |
<> | 154:37f96f9d4de2 | 1203 | return kStatus_ENET_TxFrameFail; |
<> | 154:37f96f9d4de2 | 1204 | } |
<> | 154:37f96f9d4de2 | 1205 | |
<> | 154:37f96f9d4de2 | 1206 | static bool ENET_Ptp1588ParseFrame(uint8_t *data, enet_ptp_time_data_t *ptpTsData, bool isFastEnabled) |
<> | 154:37f96f9d4de2 | 1207 | { |
<> | 154:37f96f9d4de2 | 1208 | assert(data); |
<> | 154:37f96f9d4de2 | 1209 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1210 | { |
<> | 154:37f96f9d4de2 | 1211 | assert(ptpTsData); |
<> | 154:37f96f9d4de2 | 1212 | } |
<> | 154:37f96f9d4de2 | 1213 | |
<> | 154:37f96f9d4de2 | 1214 | bool isPtpMsg = false; |
<> | 154:37f96f9d4de2 | 1215 | uint8_t *buffer = data; |
<> | 154:37f96f9d4de2 | 1216 | uint16_t ptpType; |
<> | 154:37f96f9d4de2 | 1217 | |
<> | 154:37f96f9d4de2 | 1218 | /* Check for VLAN frame. */ |
<> | 154:37f96f9d4de2 | 1219 | if (*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET) == ENET_HTONS(ENET_8021QVLAN)) |
<> | 154:37f96f9d4de2 | 1220 | { |
<> | 154:37f96f9d4de2 | 1221 | buffer += (ENET_FRAME_VLAN_HEADERLEN - ENET_FRAME_HEADERLEN); |
<> | 154:37f96f9d4de2 | 1222 | } |
<> | 154:37f96f9d4de2 | 1223 | |
<> | 154:37f96f9d4de2 | 1224 | ptpType = *(uint16_t *)(buffer + ENET_PTP1588_ETHL2_PACKETTYPE_OFFSET); |
<> | 154:37f96f9d4de2 | 1225 | switch (ENET_HTONS(ptpType)) |
<> | 154:37f96f9d4de2 | 1226 | { /* Ethernet layer 2. */ |
<> | 154:37f96f9d4de2 | 1227 | case ENET_ETHERNETL2: |
<> | 154:37f96f9d4de2 | 1228 | if (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_MSGTYPE_OFFSET) <= kENET_PtpEventMsgType) |
<> | 154:37f96f9d4de2 | 1229 | { |
<> | 154:37f96f9d4de2 | 1230 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1231 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1232 | { |
<> | 154:37f96f9d4de2 | 1233 | /* It's a ptpv2 message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1234 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1235 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_ETHL2_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1236 | ptpTsData->sequenceId = ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_ETHL2_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1237 | memcpy((void *)&ptpTsData->sourcePortId[0], (void *)(buffer + ENET_PTP1588_ETHL2_CLOCKID_OFFSET), |
<> | 154:37f96f9d4de2 | 1238 | kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1239 | } |
<> | 154:37f96f9d4de2 | 1240 | } |
<> | 154:37f96f9d4de2 | 1241 | break; |
<> | 154:37f96f9d4de2 | 1242 | /* IPV4. */ |
<> | 154:37f96f9d4de2 | 1243 | case ENET_IPV4: |
<> | 154:37f96f9d4de2 | 1244 | if ((*(uint8_t *)(buffer + ENET_PTP1588_IPVERSION_OFFSET) >> 4) == ENET_IPV4VERSION) |
<> | 154:37f96f9d4de2 | 1245 | { |
<> | 154:37f96f9d4de2 | 1246 | if (((*(uint16_t *)(buffer + ENET_PTP1588_IPV4_UDP_PORT_OFFSET)) == ENET_HTONS(kENET_PtpEventPort)) && |
<> | 154:37f96f9d4de2 | 1247 | (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_PROTOCOL_OFFSET) == ENET_UDPVERSION)) |
<> | 154:37f96f9d4de2 | 1248 | { |
<> | 154:37f96f9d4de2 | 1249 | /* Set the PTP message flag. */ |
<> | 154:37f96f9d4de2 | 1250 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1251 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1252 | { |
<> | 154:37f96f9d4de2 | 1253 | /* It's a IPV4 ptp message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1254 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1255 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_IPV4_UDP_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1256 | ptpTsData->sequenceId = |
<> | 154:37f96f9d4de2 | 1257 | ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_IPV4_UDP_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1258 | memcpy((void *)&ptpTsData->sourcePortId[0], |
<> | 154:37f96f9d4de2 | 1259 | (void *)(buffer + ENET_PTP1588_IPV4_UDP_CLKID_OFFSET), kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1260 | } |
<> | 154:37f96f9d4de2 | 1261 | } |
<> | 154:37f96f9d4de2 | 1262 | } |
<> | 154:37f96f9d4de2 | 1263 | break; |
<> | 154:37f96f9d4de2 | 1264 | /* IPV6. */ |
<> | 154:37f96f9d4de2 | 1265 | case ENET_IPV6: |
<> | 154:37f96f9d4de2 | 1266 | if ((*(uint8_t *)(buffer + ENET_PTP1588_IPVERSION_OFFSET) >> 4) == ENET_IPV6VERSION) |
<> | 154:37f96f9d4de2 | 1267 | { |
<> | 154:37f96f9d4de2 | 1268 | if (((*(uint16_t *)(buffer + ENET_PTP1588_IPV6_UDP_PORT_OFFSET)) == ENET_HTONS(kENET_PtpEventPort)) && |
<> | 154:37f96f9d4de2 | 1269 | (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_PROTOCOL_OFFSET) == ENET_UDPVERSION)) |
<> | 154:37f96f9d4de2 | 1270 | { |
<> | 154:37f96f9d4de2 | 1271 | /* Set the PTP message flag. */ |
<> | 154:37f96f9d4de2 | 1272 | isPtpMsg = true; |
<> | 154:37f96f9d4de2 | 1273 | if (!isFastEnabled) |
<> | 154:37f96f9d4de2 | 1274 | { |
<> | 154:37f96f9d4de2 | 1275 | /* It's a IPV6 ptp message and store the ptp header information. */ |
<> | 154:37f96f9d4de2 | 1276 | ptpTsData->version = (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_VERSION_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1277 | ptpTsData->messageType = (*(uint8_t *)(buffer + ENET_PTP1588_IPV6_UDP_MSGTYPE_OFFSET)) & 0x0F; |
<> | 154:37f96f9d4de2 | 1278 | ptpTsData->sequenceId = |
<> | 154:37f96f9d4de2 | 1279 | ENET_HTONS(*(uint16_t *)(buffer + ENET_PTP1588_IPV6_UDP_SEQUENCEID_OFFSET)); |
<> | 154:37f96f9d4de2 | 1280 | memcpy((void *)&ptpTsData->sourcePortId[0], |
<> | 154:37f96f9d4de2 | 1281 | (void *)(buffer + ENET_PTP1588_IPV6_UDP_CLKID_OFFSET), kENET_PtpSrcPortIdLen); |
<> | 154:37f96f9d4de2 | 1282 | } |
<> | 154:37f96f9d4de2 | 1283 | } |
<> | 154:37f96f9d4de2 | 1284 | } |
<> | 154:37f96f9d4de2 | 1285 | break; |
<> | 154:37f96f9d4de2 | 1286 | default: |
<> | 154:37f96f9d4de2 | 1287 | break; |
<> | 154:37f96f9d4de2 | 1288 | } |
<> | 154:37f96f9d4de2 | 1289 | return isPtpMsg; |
<> | 154:37f96f9d4de2 | 1290 | } |
<> | 154:37f96f9d4de2 | 1291 | |
<> | 154:37f96f9d4de2 | 1292 | void ENET_Ptp1588Configure(ENET_Type *base, enet_handle_t *handle, enet_ptp_config_t *ptpConfig) |
<> | 154:37f96f9d4de2 | 1293 | { |
<> | 154:37f96f9d4de2 | 1294 | assert(handle); |
<> | 154:37f96f9d4de2 | 1295 | assert(ptpConfig); |
<> | 154:37f96f9d4de2 | 1296 | |
<> | 154:37f96f9d4de2 | 1297 | uint32_t instance = ENET_GetInstance(base); |
<> | 154:37f96f9d4de2 | 1298 | |
<> | 154:37f96f9d4de2 | 1299 | /* Start the 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1300 | ENET_Ptp1588StartTimer(base, ptpConfig->ptp1588ClockSrc_Hz); |
<> | 154:37f96f9d4de2 | 1301 | |
<> | 154:37f96f9d4de2 | 1302 | /* Enables the time stamp interrupt for the master clock on a device. */ |
<> | 154:37f96f9d4de2 | 1303 | ENET_EnableInterrupts(base, kENET_TsTimerInterrupt); |
<> | 154:37f96f9d4de2 | 1304 | /* Enables only frame interrupt for transmit side to store the transmit |
<> | 154:37f96f9d4de2 | 1305 | frame time-stamp when the whole frame is transmitted out. */ |
<> | 154:37f96f9d4de2 | 1306 | ENET_EnableInterrupts(base, kENET_TxFrameInterrupt); |
<> | 154:37f96f9d4de2 | 1307 | ENET_DisableInterrupts(base, kENET_TxBufferInterrupt); |
<> | 154:37f96f9d4de2 | 1308 | |
<> | 154:37f96f9d4de2 | 1309 | /* Setting the receive and transmit state for transaction. */ |
<> | 154:37f96f9d4de2 | 1310 | handle->rxPtpTsDataRing.ptpTsData = ptpConfig->rxPtpTsData; |
<> | 154:37f96f9d4de2 | 1311 | handle->rxPtpTsDataRing.size = ptpConfig->ptpTsRxBuffNum; |
<> | 154:37f96f9d4de2 | 1312 | handle->rxPtpTsDataRing.front = 0; |
<> | 154:37f96f9d4de2 | 1313 | handle->rxPtpTsDataRing.end = 0; |
<> | 154:37f96f9d4de2 | 1314 | handle->txPtpTsDataRing.ptpTsData = ptpConfig->txPtpTsData; |
<> | 154:37f96f9d4de2 | 1315 | handle->txPtpTsDataRing.size = ptpConfig->ptpTsTxBuffNum; |
<> | 154:37f96f9d4de2 | 1316 | handle->txPtpTsDataRing.front = 0; |
<> | 154:37f96f9d4de2 | 1317 | handle->txPtpTsDataRing.end = 0; |
<> | 154:37f96f9d4de2 | 1318 | handle->msTimerSecond = 0; |
<> | 154:37f96f9d4de2 | 1319 | handle->txBdDirtyTime = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1320 | handle->txBdDirtyStatic = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1321 | |
<> | 154:37f96f9d4de2 | 1322 | /* Set the IRQ handler when the interrupt is enabled. */ |
<> | 154:37f96f9d4de2 | 1323 | s_enetTxIsr = ENET_TransmitIRQHandler; |
<> | 156:95d6b41a828b | 1324 | EnableIRQ(s_enetTsIrqId[instance]); |
<> | 156:95d6b41a828b | 1325 | EnableIRQ(s_enetTxIrqId[instance]); |
<> | 154:37f96f9d4de2 | 1326 | } |
<> | 154:37f96f9d4de2 | 1327 | |
<> | 154:37f96f9d4de2 | 1328 | void ENET_Ptp1588StartTimer(ENET_Type *base, uint32_t ptpClkSrc) |
<> | 154:37f96f9d4de2 | 1329 | { |
<> | 154:37f96f9d4de2 | 1330 | /* Restart PTP 1588 timer, master clock. */ |
<> | 154:37f96f9d4de2 | 1331 | base->ATCR = ENET_ATCR_RESTART_MASK; |
<> | 154:37f96f9d4de2 | 1332 | |
<> | 154:37f96f9d4de2 | 1333 | /* Initializes PTP 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1334 | base->ATINC = ENET_ATINC_INC(ENET_NANOSECOND_ONE_SECOND / ptpClkSrc); |
<> | 154:37f96f9d4de2 | 1335 | base->ATPER = ENET_NANOSECOND_ONE_SECOND; |
<> | 154:37f96f9d4de2 | 1336 | /* Sets periodical event and the event signal output assertion and Actives PTP 1588 timer. */ |
<> | 154:37f96f9d4de2 | 1337 | base->ATCR = ENET_ATCR_PEREN_MASK | ENET_ATCR_PINPER_MASK | ENET_ATCR_EN_MASK; |
<> | 154:37f96f9d4de2 | 1338 | } |
<> | 154:37f96f9d4de2 | 1339 | |
<> | 154:37f96f9d4de2 | 1340 | void ENET_Ptp1588GetTimer(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_t *ptpTime) |
<> | 154:37f96f9d4de2 | 1341 | { |
<> | 154:37f96f9d4de2 | 1342 | assert(handle); |
<> | 154:37f96f9d4de2 | 1343 | assert(ptpTime); |
<> | 154:37f96f9d4de2 | 1344 | uint16_t count = ENET_1588TIME_DELAY_COUNT; |
<> | 154:37f96f9d4de2 | 1345 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1346 | |
<> | 154:37f96f9d4de2 | 1347 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1348 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1349 | |
<> | 154:37f96f9d4de2 | 1350 | /* Get the current PTP time. */ |
<> | 154:37f96f9d4de2 | 1351 | ptpTime->second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1352 | /* Get the nanosecond from the master timer. */ |
<> | 154:37f96f9d4de2 | 1353 | base->ATCR |= ENET_ATCR_CAPTURE_MASK; |
<> | 154:37f96f9d4de2 | 1354 | /* Add at least six clock cycle delay to get accurate time. |
<> | 154:37f96f9d4de2 | 1355 | It's the requirement when the 1588 clock source is slower |
<> | 154:37f96f9d4de2 | 1356 | than the register clock. |
<> | 154:37f96f9d4de2 | 1357 | */ |
<> | 154:37f96f9d4de2 | 1358 | while (count--) |
<> | 154:37f96f9d4de2 | 1359 | { |
<> | 154:37f96f9d4de2 | 1360 | __NOP(); |
<> | 154:37f96f9d4de2 | 1361 | } |
<> | 154:37f96f9d4de2 | 1362 | /* Get the captured time. */ |
<> | 154:37f96f9d4de2 | 1363 | ptpTime->nanosecond = base->ATVR; |
<> | 154:37f96f9d4de2 | 1364 | |
<> | 154:37f96f9d4de2 | 1365 | /* Enables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1366 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1367 | } |
<> | 154:37f96f9d4de2 | 1368 | |
<> | 154:37f96f9d4de2 | 1369 | void ENET_Ptp1588SetTimer(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_t *ptpTime) |
<> | 154:37f96f9d4de2 | 1370 | { |
<> | 154:37f96f9d4de2 | 1371 | assert(handle); |
<> | 154:37f96f9d4de2 | 1372 | assert(ptpTime); |
<> | 154:37f96f9d4de2 | 1373 | |
<> | 154:37f96f9d4de2 | 1374 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1375 | |
<> | 154:37f96f9d4de2 | 1376 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1377 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1378 | |
<> | 154:37f96f9d4de2 | 1379 | /* Sets PTP timer. */ |
<> | 154:37f96f9d4de2 | 1380 | handle->msTimerSecond = ptpTime->second; |
<> | 154:37f96f9d4de2 | 1381 | base->ATVR = ptpTime->nanosecond; |
<> | 154:37f96f9d4de2 | 1382 | |
<> | 154:37f96f9d4de2 | 1383 | /* Enables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1384 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1385 | } |
<> | 154:37f96f9d4de2 | 1386 | |
<> | 154:37f96f9d4de2 | 1387 | void ENET_Ptp1588AdjustTimer(ENET_Type *base, uint32_t corrIncrease, uint32_t corrPeriod) |
<> | 154:37f96f9d4de2 | 1388 | { |
<> | 154:37f96f9d4de2 | 1389 | /* Set correction for PTP timer increment. */ |
<> | 154:37f96f9d4de2 | 1390 | base->ATINC = (base->ATINC & ~ENET_ATINC_INC_CORR_MASK) | (corrIncrease << ENET_ATINC_INC_CORR_SHIFT); |
<> | 154:37f96f9d4de2 | 1391 | /* Set correction for PTP timer period. */ |
<> | 154:37f96f9d4de2 | 1392 | base->ATCOR = (base->ATCOR & ~ENET_ATCOR_COR_MASK) | (corrPeriod << ENET_ATCOR_COR_SHIFT); |
<> | 154:37f96f9d4de2 | 1393 | } |
<> | 154:37f96f9d4de2 | 1394 | |
<> | 154:37f96f9d4de2 | 1395 | static status_t ENET_Ptp1588UpdateTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1396 | { |
<> | 154:37f96f9d4de2 | 1397 | assert(ptpTsDataRing); |
<> | 154:37f96f9d4de2 | 1398 | assert(ptpTsDataRing->ptpTsData); |
<> | 154:37f96f9d4de2 | 1399 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1400 | |
<> | 154:37f96f9d4de2 | 1401 | uint16_t usedBuffer = 0; |
<> | 154:37f96f9d4de2 | 1402 | |
<> | 154:37f96f9d4de2 | 1403 | /* Check if the buffers ring is full. */ |
<> | 154:37f96f9d4de2 | 1404 | if (ptpTsDataRing->end >= ptpTsDataRing->front) |
<> | 154:37f96f9d4de2 | 1405 | { |
<> | 154:37f96f9d4de2 | 1406 | usedBuffer = ptpTsDataRing->end - ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1407 | } |
<> | 154:37f96f9d4de2 | 1408 | else |
<> | 154:37f96f9d4de2 | 1409 | { |
<> | 154:37f96f9d4de2 | 1410 | usedBuffer = ptpTsDataRing->size - (ptpTsDataRing->front - ptpTsDataRing->end); |
<> | 154:37f96f9d4de2 | 1411 | } |
<> | 154:37f96f9d4de2 | 1412 | |
<> | 154:37f96f9d4de2 | 1413 | if (usedBuffer == ptpTsDataRing->size) |
<> | 154:37f96f9d4de2 | 1414 | { |
<> | 154:37f96f9d4de2 | 1415 | return kStatus_ENET_PtpTsRingFull; |
<> | 154:37f96f9d4de2 | 1416 | } |
<> | 154:37f96f9d4de2 | 1417 | |
<> | 154:37f96f9d4de2 | 1418 | /* Copy the new data into the buffer. */ |
<> | 154:37f96f9d4de2 | 1419 | memcpy((ptpTsDataRing->ptpTsData + ptpTsDataRing->end), ptpTimeData, sizeof(enet_ptp_time_data_t)); |
<> | 154:37f96f9d4de2 | 1420 | |
<> | 154:37f96f9d4de2 | 1421 | /* Increase the buffer pointer to the next empty one. */ |
<> | 154:37f96f9d4de2 | 1422 | ptpTsDataRing->end = (ptpTsDataRing->end + 1) % ptpTsDataRing->size; |
<> | 154:37f96f9d4de2 | 1423 | |
<> | 154:37f96f9d4de2 | 1424 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1425 | } |
<> | 154:37f96f9d4de2 | 1426 | |
<> | 154:37f96f9d4de2 | 1427 | static status_t ENET_Ptp1588SearchTimeRing(enet_ptp_time_data_ring_t *ptpTsDataRing, enet_ptp_time_data_t *ptpTimedata) |
<> | 154:37f96f9d4de2 | 1428 | { |
<> | 154:37f96f9d4de2 | 1429 | assert(ptpTsDataRing); |
<> | 154:37f96f9d4de2 | 1430 | assert(ptpTsDataRing->ptpTsData); |
<> | 154:37f96f9d4de2 | 1431 | assert(ptpTimedata); |
<> | 154:37f96f9d4de2 | 1432 | |
<> | 154:37f96f9d4de2 | 1433 | uint32_t index; |
<> | 154:37f96f9d4de2 | 1434 | uint32_t size; |
<> | 154:37f96f9d4de2 | 1435 | uint16_t usedBuffer = 0; |
<> | 154:37f96f9d4de2 | 1436 | |
<> | 154:37f96f9d4de2 | 1437 | /* Check the PTP 1588 timestamp ring. */ |
<> | 154:37f96f9d4de2 | 1438 | if (ptpTsDataRing->front == ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1439 | { |
<> | 154:37f96f9d4de2 | 1440 | return kStatus_ENET_PtpTsRingEmpty; |
<> | 154:37f96f9d4de2 | 1441 | } |
<> | 154:37f96f9d4de2 | 1442 | |
<> | 154:37f96f9d4de2 | 1443 | /* Search the element in the ring buffer */ |
<> | 154:37f96f9d4de2 | 1444 | index = ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1445 | size = ptpTsDataRing->size; |
<> | 154:37f96f9d4de2 | 1446 | while (index != ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1447 | { |
<> | 154:37f96f9d4de2 | 1448 | if (((ptpTsDataRing->ptpTsData + index)->sequenceId == ptpTimedata->sequenceId) && |
<> | 154:37f96f9d4de2 | 1449 | (!memcmp(((void *)&(ptpTsDataRing->ptpTsData + index)->sourcePortId[0]), |
<> | 154:37f96f9d4de2 | 1450 | (void *)&ptpTimedata->sourcePortId[0], kENET_PtpSrcPortIdLen)) && |
<> | 154:37f96f9d4de2 | 1451 | ((ptpTsDataRing->ptpTsData + index)->version == ptpTimedata->version) && |
<> | 154:37f96f9d4de2 | 1452 | ((ptpTsDataRing->ptpTsData + index)->messageType == ptpTimedata->messageType)) |
<> | 154:37f96f9d4de2 | 1453 | { |
<> | 154:37f96f9d4de2 | 1454 | break; |
<> | 154:37f96f9d4de2 | 1455 | } |
<> | 154:37f96f9d4de2 | 1456 | |
<> | 154:37f96f9d4de2 | 1457 | /* Increase the ptp ring index. */ |
<> | 154:37f96f9d4de2 | 1458 | index = (index + 1) % size; |
<> | 154:37f96f9d4de2 | 1459 | } |
<> | 154:37f96f9d4de2 | 1460 | |
<> | 154:37f96f9d4de2 | 1461 | if (index == ptpTsDataRing->end) |
<> | 154:37f96f9d4de2 | 1462 | { |
<> | 154:37f96f9d4de2 | 1463 | /* Check if buffers is full. */ |
<> | 154:37f96f9d4de2 | 1464 | if (ptpTsDataRing->end >= ptpTsDataRing->front) |
<> | 154:37f96f9d4de2 | 1465 | { |
<> | 154:37f96f9d4de2 | 1466 | usedBuffer = ptpTsDataRing->end - ptpTsDataRing->front; |
<> | 154:37f96f9d4de2 | 1467 | } |
<> | 154:37f96f9d4de2 | 1468 | else |
<> | 154:37f96f9d4de2 | 1469 | { |
<> | 154:37f96f9d4de2 | 1470 | usedBuffer = ptpTsDataRing->size - (ptpTsDataRing->front - ptpTsDataRing->end); |
<> | 154:37f96f9d4de2 | 1471 | } |
<> | 154:37f96f9d4de2 | 1472 | |
<> | 154:37f96f9d4de2 | 1473 | if (usedBuffer == ptpTsDataRing->size) |
<> | 154:37f96f9d4de2 | 1474 | { /* Drop one in the front. */ |
<> | 154:37f96f9d4de2 | 1475 | ptpTsDataRing->front = (ptpTsDataRing->front + 1) % size; |
<> | 154:37f96f9d4de2 | 1476 | } |
<> | 154:37f96f9d4de2 | 1477 | return kStatus_ENET_PtpTsRingFull; |
<> | 154:37f96f9d4de2 | 1478 | } |
<> | 154:37f96f9d4de2 | 1479 | |
<> | 154:37f96f9d4de2 | 1480 | /* Get the right timestamp of the required ptp messag. */ |
<> | 154:37f96f9d4de2 | 1481 | ptpTimedata->timeStamp.second = (ptpTsDataRing->ptpTsData + index)->timeStamp.second; |
<> | 154:37f96f9d4de2 | 1482 | ptpTimedata->timeStamp.nanosecond = (ptpTsDataRing->ptpTsData + index)->timeStamp.nanosecond; |
<> | 154:37f96f9d4de2 | 1483 | |
<> | 154:37f96f9d4de2 | 1484 | /* Increase the index. */ |
<> | 154:37f96f9d4de2 | 1485 | ptpTsDataRing->front = (ptpTsDataRing->front + 1) % size; |
<> | 154:37f96f9d4de2 | 1486 | |
<> | 154:37f96f9d4de2 | 1487 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1488 | } |
<> | 154:37f96f9d4de2 | 1489 | |
<> | 154:37f96f9d4de2 | 1490 | static status_t ENET_StoreRxFrameTime(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1491 | { |
<> | 154:37f96f9d4de2 | 1492 | assert(handle); |
<> | 154:37f96f9d4de2 | 1493 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1494 | |
<> | 154:37f96f9d4de2 | 1495 | bool ptpTimerWrap = false; |
<> | 154:37f96f9d4de2 | 1496 | enet_ptp_time_t ptpTimer; |
<> | 154:37f96f9d4de2 | 1497 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1498 | |
<> | 154:37f96f9d4de2 | 1499 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1500 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1501 | |
<> | 154:37f96f9d4de2 | 1502 | /* Get current PTP timer nanosecond value. */ |
<> | 154:37f96f9d4de2 | 1503 | ENET_Ptp1588GetTimer(base, handle, &ptpTimer); |
<> | 154:37f96f9d4de2 | 1504 | |
<> | 154:37f96f9d4de2 | 1505 | /* Get PTP timer wrap event. */ |
<> | 154:37f96f9d4de2 | 1506 | ptpTimerWrap = base->EIR & kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1507 | |
<> | 154:37f96f9d4de2 | 1508 | /* Get transmit time stamp second. */ |
<> | 154:37f96f9d4de2 | 1509 | if ((ptpTimer.nanosecond > ptpTimeData->timeStamp.nanosecond) || |
<> | 154:37f96f9d4de2 | 1510 | ((ptpTimer.nanosecond < ptpTimeData->timeStamp.nanosecond) && ptpTimerWrap)) |
<> | 154:37f96f9d4de2 | 1511 | { |
<> | 154:37f96f9d4de2 | 1512 | ptpTimeData->timeStamp.second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1513 | } |
<> | 154:37f96f9d4de2 | 1514 | else |
<> | 154:37f96f9d4de2 | 1515 | { |
<> | 154:37f96f9d4de2 | 1516 | ptpTimeData->timeStamp.second = handle->msTimerSecond - 1; |
<> | 154:37f96f9d4de2 | 1517 | } |
<> | 154:37f96f9d4de2 | 1518 | /* Enable the interrupt. */ |
<> | 154:37f96f9d4de2 | 1519 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1520 | |
<> | 154:37f96f9d4de2 | 1521 | /* Store the timestamp to the receive time stamp ring. */ |
<> | 154:37f96f9d4de2 | 1522 | /* Check if the buffers ring is full. */ |
<> | 154:37f96f9d4de2 | 1523 | return ENET_Ptp1588UpdateTimeRing(&handle->rxPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1524 | } |
<> | 154:37f96f9d4de2 | 1525 | |
<> | 154:37f96f9d4de2 | 1526 | static status_t ENET_StoreTxFrameTime(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1527 | { |
<> | 154:37f96f9d4de2 | 1528 | assert(handle); |
<> | 154:37f96f9d4de2 | 1529 | |
<> | 154:37f96f9d4de2 | 1530 | uint32_t primask; |
<> | 154:37f96f9d4de2 | 1531 | bool ptpTimerWrap; |
<> | 154:37f96f9d4de2 | 1532 | bool isPtpEventMessage = false; |
<> | 154:37f96f9d4de2 | 1533 | enet_ptp_time_data_t ptpTimeData; |
<> | 154:37f96f9d4de2 | 1534 | volatile enet_tx_bd_struct_t *curBuffDescrip = handle->txBdDirtyTime; |
<> | 154:37f96f9d4de2 | 1535 | |
<> | 154:37f96f9d4de2 | 1536 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1537 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1538 | { |
<> | 154:37f96f9d4de2 | 1539 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1540 | } |
<> | 154:37f96f9d4de2 | 1541 | |
<> | 154:37f96f9d4de2 | 1542 | /* Parse the PTP message. */ |
<> | 154:37f96f9d4de2 | 1543 | isPtpEventMessage = ENET_Ptp1588ParseFrame(curBuffDescrip->buffer, &ptpTimeData, false); |
<> | 154:37f96f9d4de2 | 1544 | if (isPtpEventMessage) |
<> | 154:37f96f9d4de2 | 1545 | { |
<> | 154:37f96f9d4de2 | 1546 | do |
<> | 154:37f96f9d4de2 | 1547 | { |
<> | 154:37f96f9d4de2 | 1548 | /* Increase current buffer descriptor to the next one. */ |
<> | 154:37f96f9d4de2 | 1549 | if (handle->txBdDirtyTime->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) |
<> | 154:37f96f9d4de2 | 1550 | { |
<> | 154:37f96f9d4de2 | 1551 | handle->txBdDirtyTime = handle->txBdBase; |
<> | 154:37f96f9d4de2 | 1552 | } |
<> | 154:37f96f9d4de2 | 1553 | else |
<> | 154:37f96f9d4de2 | 1554 | { |
<> | 154:37f96f9d4de2 | 1555 | handle->txBdDirtyTime++; |
<> | 154:37f96f9d4de2 | 1556 | } |
<> | 154:37f96f9d4de2 | 1557 | |
<> | 154:37f96f9d4de2 | 1558 | /* Do time stamp check on the last buffer descriptor of the frame. */ |
<> | 154:37f96f9d4de2 | 1559 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_LAST_MASK) |
<> | 154:37f96f9d4de2 | 1560 | { |
<> | 154:37f96f9d4de2 | 1561 | /* Disables the interrupt. */ |
<> | 154:37f96f9d4de2 | 1562 | primask = DisableGlobalIRQ(); |
<> | 154:37f96f9d4de2 | 1563 | |
<> | 154:37f96f9d4de2 | 1564 | /* Get current PTP timer nanosecond value. */ |
<> | 154:37f96f9d4de2 | 1565 | ENET_Ptp1588GetTimer(base, handle, &ptpTimeData.timeStamp); |
<> | 154:37f96f9d4de2 | 1566 | |
<> | 154:37f96f9d4de2 | 1567 | /* Get PTP timer wrap event. */ |
<> | 154:37f96f9d4de2 | 1568 | ptpTimerWrap = base->EIR & kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1569 | |
<> | 154:37f96f9d4de2 | 1570 | /* Get transmit time stamp second. */ |
<> | 154:37f96f9d4de2 | 1571 | if ((ptpTimeData.timeStamp.nanosecond > curBuffDescrip->timestamp) || |
<> | 154:37f96f9d4de2 | 1572 | ((ptpTimeData.timeStamp.nanosecond < curBuffDescrip->timestamp) && ptpTimerWrap)) |
<> | 154:37f96f9d4de2 | 1573 | { |
<> | 154:37f96f9d4de2 | 1574 | ptpTimeData.timeStamp.second = handle->msTimerSecond; |
<> | 154:37f96f9d4de2 | 1575 | } |
<> | 154:37f96f9d4de2 | 1576 | else |
<> | 154:37f96f9d4de2 | 1577 | { |
<> | 154:37f96f9d4de2 | 1578 | ptpTimeData.timeStamp.second = handle->msTimerSecond - 1; |
<> | 154:37f96f9d4de2 | 1579 | } |
<> | 154:37f96f9d4de2 | 1580 | |
<> | 154:37f96f9d4de2 | 1581 | /* Enable the interrupt. */ |
<> | 154:37f96f9d4de2 | 1582 | EnableGlobalIRQ(primask); |
<> | 154:37f96f9d4de2 | 1583 | |
<> | 154:37f96f9d4de2 | 1584 | /* Store the timestamp to the transmit timestamp ring. */ |
<> | 154:37f96f9d4de2 | 1585 | return ENET_Ptp1588UpdateTimeRing(&handle->txPtpTsDataRing, &ptpTimeData); |
<> | 154:37f96f9d4de2 | 1586 | } |
<> | 154:37f96f9d4de2 | 1587 | |
<> | 154:37f96f9d4de2 | 1588 | /* Get the current transmit buffer descriptor. */ |
<> | 154:37f96f9d4de2 | 1589 | curBuffDescrip = handle->txBdDirtyTime; |
<> | 154:37f96f9d4de2 | 1590 | |
<> | 154:37f96f9d4de2 | 1591 | /* Get the control status data, If the buffer descriptor has not been processed break out. */ |
<> | 154:37f96f9d4de2 | 1592 | if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) |
<> | 154:37f96f9d4de2 | 1593 | { |
<> | 154:37f96f9d4de2 | 1594 | return kStatus_ENET_TxFrameBusy; |
<> | 154:37f96f9d4de2 | 1595 | } |
<> | 154:37f96f9d4de2 | 1596 | } while (handle->txBdDirtyTime != handle->txBdCurrent); |
<> | 154:37f96f9d4de2 | 1597 | return kStatus_ENET_TxFrameFail; |
<> | 154:37f96f9d4de2 | 1598 | } |
<> | 154:37f96f9d4de2 | 1599 | return kStatus_Success; |
<> | 154:37f96f9d4de2 | 1600 | } |
<> | 154:37f96f9d4de2 | 1601 | |
<> | 154:37f96f9d4de2 | 1602 | status_t ENET_GetTxFrameTime(enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1603 | { |
<> | 154:37f96f9d4de2 | 1604 | assert(handle); |
<> | 154:37f96f9d4de2 | 1605 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1606 | |
<> | 154:37f96f9d4de2 | 1607 | return ENET_Ptp1588SearchTimeRing(&handle->txPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1608 | } |
<> | 154:37f96f9d4de2 | 1609 | |
<> | 154:37f96f9d4de2 | 1610 | status_t ENET_GetRxFrameTime(enet_handle_t *handle, enet_ptp_time_data_t *ptpTimeData) |
<> | 154:37f96f9d4de2 | 1611 | { |
<> | 154:37f96f9d4de2 | 1612 | assert(handle); |
<> | 154:37f96f9d4de2 | 1613 | assert(ptpTimeData); |
<> | 154:37f96f9d4de2 | 1614 | |
<> | 154:37f96f9d4de2 | 1615 | return ENET_Ptp1588SearchTimeRing(&handle->rxPtpTsDataRing, ptpTimeData); |
<> | 154:37f96f9d4de2 | 1616 | } |
<> | 154:37f96f9d4de2 | 1617 | |
<> | 154:37f96f9d4de2 | 1618 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1619 | |
<> | 154:37f96f9d4de2 | 1620 | void ENET_TransmitIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1621 | { |
<> | 154:37f96f9d4de2 | 1622 | assert(handle); |
<> | 154:37f96f9d4de2 | 1623 | |
<> | 154:37f96f9d4de2 | 1624 | /* Check if the transmit interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1625 | while ((kENET_TxBufferInterrupt | kENET_TxFrameInterrupt) & base->EIR) |
<> | 154:37f96f9d4de2 | 1626 | { |
<> | 154:37f96f9d4de2 | 1627 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1628 | if (base->EIR & kENET_TxFrameInterrupt) |
<> | 154:37f96f9d4de2 | 1629 | { |
<> | 154:37f96f9d4de2 | 1630 | /* Store the transmit timestamp from the buffer descriptor should be done here. */ |
<> | 154:37f96f9d4de2 | 1631 | ENET_StoreTxFrameTime(base, handle); |
<> | 154:37f96f9d4de2 | 1632 | } |
<> | 154:37f96f9d4de2 | 1633 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1634 | |
<> | 154:37f96f9d4de2 | 1635 | /* Clear the transmit interrupt event. */ |
<> | 154:37f96f9d4de2 | 1636 | base->EIR = kENET_TxFrameInterrupt | kENET_TxBufferInterrupt; |
<> | 154:37f96f9d4de2 | 1637 | |
<> | 154:37f96f9d4de2 | 1638 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1639 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1640 | { |
<> | 154:37f96f9d4de2 | 1641 | handle->callback(base, handle, kENET_TxEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1642 | } |
<> | 154:37f96f9d4de2 | 1643 | } |
<> | 154:37f96f9d4de2 | 1644 | } |
<> | 154:37f96f9d4de2 | 1645 | |
<> | 154:37f96f9d4de2 | 1646 | void ENET_ReceiveIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1647 | { |
<> | 154:37f96f9d4de2 | 1648 | assert(handle); |
<> | 154:37f96f9d4de2 | 1649 | |
<> | 154:37f96f9d4de2 | 1650 | /* Check if the receive interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1651 | while ((kENET_RxBufferInterrupt | kENET_RxFrameInterrupt) & base->EIR) |
<> | 154:37f96f9d4de2 | 1652 | { |
<> | 154:37f96f9d4de2 | 1653 | /* Clear the transmit interrupt event. */ |
<> | 154:37f96f9d4de2 | 1654 | base->EIR = kENET_RxFrameInterrupt | kENET_RxBufferInterrupt; |
<> | 154:37f96f9d4de2 | 1655 | |
<> | 154:37f96f9d4de2 | 1656 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1657 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1658 | { |
<> | 154:37f96f9d4de2 | 1659 | handle->callback(base, handle, kENET_RxEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1660 | } |
<> | 154:37f96f9d4de2 | 1661 | } |
<> | 154:37f96f9d4de2 | 1662 | } |
<> | 154:37f96f9d4de2 | 1663 | |
<> | 154:37f96f9d4de2 | 1664 | void ENET_ErrorIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1665 | { |
<> | 154:37f96f9d4de2 | 1666 | assert(handle); |
<> | 154:37f96f9d4de2 | 1667 | |
<> | 154:37f96f9d4de2 | 1668 | uint32_t errMask = kENET_BabrInterrupt | kENET_BabtInterrupt | kENET_EBusERInterrupt | kENET_PayloadRxInterrupt | |
<> | 154:37f96f9d4de2 | 1669 | kENET_LateCollisionInterrupt | kENET_RetryLimitInterrupt | kENET_UnderrunInterrupt; |
<> | 154:37f96f9d4de2 | 1670 | |
<> | 154:37f96f9d4de2 | 1671 | /* Check if the error interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1672 | if (kENET_WakeupInterrupt & base->EIR) |
<> | 154:37f96f9d4de2 | 1673 | { |
<> | 154:37f96f9d4de2 | 1674 | /* Clear the wakeup interrupt. */ |
<> | 154:37f96f9d4de2 | 1675 | base->EIR = kENET_WakeupInterrupt; |
<> | 154:37f96f9d4de2 | 1676 | /* wake up and enter the normal mode. */ |
<> | 154:37f96f9d4de2 | 1677 | ENET_EnableSleepMode(base, false); |
<> | 154:37f96f9d4de2 | 1678 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1679 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1680 | { |
<> | 154:37f96f9d4de2 | 1681 | handle->callback(base, handle, kENET_WakeUpEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1682 | } |
<> | 154:37f96f9d4de2 | 1683 | } |
<> | 154:37f96f9d4de2 | 1684 | else |
<> | 154:37f96f9d4de2 | 1685 | { |
<> | 154:37f96f9d4de2 | 1686 | /* Clear the error interrupt event status. */ |
<> | 154:37f96f9d4de2 | 1687 | errMask &= base->EIR; |
<> | 154:37f96f9d4de2 | 1688 | base->EIR = errMask; |
<> | 154:37f96f9d4de2 | 1689 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1690 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1691 | { |
<> | 154:37f96f9d4de2 | 1692 | handle->callback(base, handle, kENET_ErrEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1693 | } |
<> | 154:37f96f9d4de2 | 1694 | } |
<> | 154:37f96f9d4de2 | 1695 | } |
<> | 154:37f96f9d4de2 | 1696 | #ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE |
<> | 154:37f96f9d4de2 | 1697 | void ENET_Ptp1588TimerIRQHandler(ENET_Type *base, enet_handle_t *handle) |
<> | 154:37f96f9d4de2 | 1698 | { |
<> | 154:37f96f9d4de2 | 1699 | assert(handle); |
<> | 154:37f96f9d4de2 | 1700 | |
<> | 154:37f96f9d4de2 | 1701 | /* Check if the PTP time stamp interrupt happen. */ |
<> | 154:37f96f9d4de2 | 1702 | if (kENET_TsTimerInterrupt & base->EIR) |
<> | 154:37f96f9d4de2 | 1703 | { |
<> | 154:37f96f9d4de2 | 1704 | /* Clear the time stamp interrupt. */ |
<> | 154:37f96f9d4de2 | 1705 | base->EIR = kENET_TsTimerInterrupt; |
<> | 154:37f96f9d4de2 | 1706 | |
<> | 154:37f96f9d4de2 | 1707 | /* Increase timer second counter. */ |
<> | 154:37f96f9d4de2 | 1708 | handle->msTimerSecond++; |
<> | 154:37f96f9d4de2 | 1709 | |
<> | 154:37f96f9d4de2 | 1710 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1711 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1712 | { |
<> | 154:37f96f9d4de2 | 1713 | handle->callback(base, handle, kENET_TimeStampEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1714 | } |
<> | 154:37f96f9d4de2 | 1715 | } |
<> | 154:37f96f9d4de2 | 1716 | else |
<> | 154:37f96f9d4de2 | 1717 | { |
<> | 154:37f96f9d4de2 | 1718 | /* Clear the time stamp interrupt. */ |
<> | 154:37f96f9d4de2 | 1719 | base->EIR = kENET_TsAvailInterrupt; |
<> | 154:37f96f9d4de2 | 1720 | /* Callback function. */ |
<> | 154:37f96f9d4de2 | 1721 | if (handle->callback) |
<> | 154:37f96f9d4de2 | 1722 | { |
<> | 154:37f96f9d4de2 | 1723 | handle->callback(base, handle, kENET_TimeStampAvailEvent, handle->userData); |
<> | 154:37f96f9d4de2 | 1724 | } |
<> | 154:37f96f9d4de2 | 1725 | } |
<> | 154:37f96f9d4de2 | 1726 | } |
<> | 154:37f96f9d4de2 | 1727 | |
<> | 154:37f96f9d4de2 | 1728 | void ENET_1588_Timer_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1729 | { |
<> | 154:37f96f9d4de2 | 1730 | ENET_Ptp1588TimerIRQHandler(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1731 | } |
<> | 154:37f96f9d4de2 | 1732 | #endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ |
<> | 154:37f96f9d4de2 | 1733 | |
<> | 154:37f96f9d4de2 | 1734 | void ENET_Transmit_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1735 | { |
<> | 154:37f96f9d4de2 | 1736 | s_enetTxIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1737 | } |
<> | 154:37f96f9d4de2 | 1738 | |
<> | 154:37f96f9d4de2 | 1739 | void ENET_Receive_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1740 | { |
<> | 154:37f96f9d4de2 | 1741 | s_enetRxIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1742 | } |
<> | 154:37f96f9d4de2 | 1743 | |
<> | 154:37f96f9d4de2 | 1744 | void ENET_Error_IRQHandler(void) |
<> | 154:37f96f9d4de2 | 1745 | { |
<> | 154:37f96f9d4de2 | 1746 | s_enetErrIsr(ENET, s_ENETHandle[0]); |
<> | 154:37f96f9d4de2 | 1747 | } |