1 /*!
2     \file    gd32f4xx_enet.c
3     \brief   ENET driver
4 
5     \version 2016-08-15, V1.0.0, firmware for GD32F4xx
6     \version 2018-12-12, V2.0.0, firmware for GD32F4xx
7     \version 2020-09-30, V2.1.0, firmware for GD32F4xx
8     \version 2022-03-09, V3.0.0, firmware for GD32F4xx
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13     Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15 
16     1. Redistributions of source code must retain the above copyright notice, this
17        list of conditions and the following disclaimer.
18     2. Redistributions in binary form must reproduce the above copyright notice,
19        this list of conditions and the following disclaimer in the documentation
20        and/or other materials provided with the distribution.
21     3. Neither the name of the copyright holder nor the names of its contributors
22        may be used to endorse or promote products derived from this software without
23        specific prior written permission.
24 
25     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36 
37 #include "gd32f4xx_enet.h"
38 
39 #if defined   (__CC_ARM)                                    /*!< ARM compiler */
40 __align(4)
41 enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM];        /*!< ENET RxDMA descriptor */
42 __align(4)
43 enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM];        /*!< ENET TxDMA descriptor */
44 __align(4)
45 uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET receive buffer */
46 __align(4)
47 uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET transmit buffer */
48 
49 #elif defined ( __ICCARM__ )                                /*!< IAR compiler */
50 #pragma data_alignment=4
51 enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM];        /*!< ENET RxDMA descriptor */
52 #pragma data_alignment=4
53 enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM];        /*!< ENET TxDMA descriptor */
54 #pragma data_alignment=4
55 uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE];           /*!< ENET receive buffer */
56 #pragma data_alignment=4
57 uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE];           /*!< ENET transmit buffer */
58 
59 #elif defined (__GNUC__)        /* GNU Compiler */
60 enet_descriptors_struct  rxdesc_tab[ENET_RXBUF_NUM] __attribute__((aligned(4)));          /*!< ENET RxDMA descriptor */
61 enet_descriptors_struct  txdesc_tab[ENET_TXBUF_NUM] __attribute__((aligned(4)));          /*!< ENET TxDMA descriptor */
62 uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE] __attribute__((aligned(4)));             /*!< ENET receive buffer */
63 uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE] __attribute__((aligned(4)));             /*!< ENET transmit buffer */
64 
65 #endif /* __CC_ARM */
66 
67 /* global transmit and receive descriptors pointers */
68 enet_descriptors_struct  *dma_current_txdesc;
69 enet_descriptors_struct  *dma_current_rxdesc;
70 
71 /* structure pointer of ptp descriptor for normal mode */
72 enet_descriptors_struct  *dma_current_ptp_txdesc = NULL;
73 enet_descriptors_struct  *dma_current_ptp_rxdesc = NULL;
74 
75 /* init structure parameters for ENET initialization */
76 static enet_initpara_struct enet_initpara = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
77 static uint32_t enet_unknow_err = 0U;
78 /* array of register offset for debug information get */
79 static const uint16_t enet_reg_tab[] = {
80     0x0000, 0x0004, 0x0008, 0x000C, 0x0010, 0x0014, 0x0018, 0x001C, 0x0028, 0x002C, 0x0034,
81     0x0038, 0x003C, 0x0040, 0x0044, 0x0048, 0x004C, 0x0050, 0x0054, 0x0058, 0x005C, 0x1080,
82 
83     0x0100, 0x0104, 0x0108, 0x010C, 0x0110, 0x014C, 0x0150, 0x0168, 0x0194, 0x0198, 0x01C4,
84 
85     0x0700, 0x0704, 0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, 0x0728, 0x072C,
86 
87     0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C, 0x1020, 0x1024, 0x1048,
88     0x104C, 0x1050, 0x1054
89 };
90 
91 /* initialize ENET peripheral with generally concerned parameters, call it by enet_init() */
92 static void enet_default_init(void);
93 #ifdef USE_DELAY
94 /* user can provide more timing precise _ENET_DELAY_ function */
95 #define _ENET_DELAY_                              delay_ms
96 #else
97 /* insert a delay time */
98 static void enet_delay(uint32_t ncount);
99 /* default _ENET_DELAY_ function with less precise timing */
100 #define _ENET_DELAY_                              enet_delay
101 #endif
102 
103 
104 /*!
105     \brief    deinitialize the ENET, and reset structure parameters for ENET initialization
106     \param[in]  none
107     \param[out] none
108     \retval     none
109 */
enet_deinit(void)110 void enet_deinit(void)
111 {
112     rcu_periph_reset_enable(RCU_ENETRST);
113     rcu_periph_reset_disable(RCU_ENETRST);
114     enet_initpara_reset();
115 }
116 
117 /*!
118     \brief    configure the parameters which are usually less cared for initialization
119                 note -- this function must be called before enet_init(), otherwise
120                 configuration will be no effect
121     \param[in]  option: different function option, which is related to several parameters, refer to enet_option_enum
122                 only one parameter can be selected which is shown as below
123       \arg        FORWARD_OPTION: choose to configure the frame forward related parameters
124       \arg        DMABUS_OPTION: choose to configure the DMA bus mode related parameters
125       \arg        DMA_MAXBURST_OPTION: choose to configure the DMA max burst related parameters
126       \arg        DMA_ARBITRATION_OPTION: choose to configure the DMA arbitration related parameters
127       \arg        STORE_OPTION: choose to configure the store forward mode related parameters
128       \arg        DMA_OPTION: choose to configure the DMA descriptor related parameters
129       \arg        VLAN_OPTION: choose to configure vlan related parameters
130       \arg        FLOWCTL_OPTION: choose to configure flow control related parameters
131       \arg        HASHH_OPTION: choose to configure hash high
132       \arg        HASHL_OPTION: choose to configure hash low
133       \arg        FILTER_OPTION: choose to configure frame filter related parameters
134       \arg        HALFDUPLEX_OPTION: choose to configure halfduplex mode related parameters
135       \arg        TIMER_OPTION: choose to configure time counter related parameters
136       \arg        INTERFRAMEGAP_OPTION: choose to configure the inter frame gap related parameters
137     \param[in]  para: the related parameters according to the option
138                 all the related parameters should be configured which are shown as below
139                       FORWARD_OPTION related parameters:
140                       -  ENET_AUTO_PADCRC_DROP_ENABLE/ ENET_AUTO_PADCRC_DROP_DISABLE ;
141                       -  ENET_TYPEFRAME_CRC_DROP_ENABLE/ ENET_TYPEFRAME_CRC_DROP_DISABLE ;
142                       -  ENET_FORWARD_ERRFRAMES_ENABLE/ ENET_FORWARD_ERRFRAMES_DISABLE ;
143                       -  ENET_FORWARD_UNDERSZ_GOODFRAMES_ENABLE/ ENET_FORWARD_UNDERSZ_GOODFRAMES_DISABLE .
144                       DMABUS_OPTION related parameters:
145                       -  ENET_ADDRESS_ALIGN_ENABLE/ ENET_ADDRESS_ALIGN_DISABLE ;
146                       -  ENET_FIXED_BURST_ENABLE/ ENET_FIXED_BURST_DISABLE ;
147                       -  ENET_MIXED_BURST_ENABLE/ ENET_MIXED_BURST_DISABLE ;
148                       DMA_MAXBURST_OPTION related parameters:
149                       -  ENET_RXDP_1BEAT/ ENET_RXDP_2BEAT/ ENET_RXDP_4BEAT/
150                          ENET_RXDP_8BEAT/ ENET_RXDP_16BEAT/ ENET_RXDP_32BEAT/
151                          ENET_RXDP_4xPGBL_4BEAT/ ENET_RXDP_4xPGBL_8BEAT/
152                          ENET_RXDP_4xPGBL_16BEAT/ ENET_RXDP_4xPGBL_32BEAT/
153                          ENET_RXDP_4xPGBL_64BEAT/ ENET_RXDP_4xPGBL_128BEAT ;
154                       -  ENET_PGBL_1BEAT/ ENET_PGBL_2BEAT/ ENET_PGBL_4BEAT/
155                          ENET_PGBL_8BEAT/ ENET_PGBL_16BEAT/ ENET_PGBL_32BEAT/
156                          ENET_PGBL_4xPGBL_4BEAT/ ENET_PGBL_4xPGBL_8BEAT/
157                          ENET_PGBL_4xPGBL_16BEAT/ ENET_PGBL_4xPGBL_32BEAT/
158                          ENET_PGBL_4xPGBL_64BEAT/ ENET_PGBL_4xPGBL_128BEAT ;
159                       -  ENET_RXTX_DIFFERENT_PGBL/ ENET_RXTX_SAME_PGBL ;
160                       DMA_ARBITRATION_OPTION related parameters:
161                       -  ENET_ARBITRATION_RXPRIORTX
162                       -  ENET_ARBITRATION_RXTX_1_1/ ENET_ARBITRATION_RXTX_2_1/
163                          ENET_ARBITRATION_RXTX_3_1/ ENET_ARBITRATION_RXTX_4_1/.
164                       STORE_OPTION related parameters:
165                       -  ENET_RX_MODE_STOREFORWARD/ ENET_RX_MODE_CUTTHROUGH ;
166                       -  ENET_TX_MODE_STOREFORWARD/ ENET_TX_MODE_CUTTHROUGH ;
167                       -  ENET_RX_THRESHOLD_64BYTES/ ENET_RX_THRESHOLD_32BYTES/
168                          ENET_RX_THRESHOLD_96BYTES/ ENET_RX_THRESHOLD_128BYTES ;
169                       -  ENET_TX_THRESHOLD_64BYTES/ ENET_TX_THRESHOLD_128BYTES/
170                          ENET_TX_THRESHOLD_192BYTES/ ENET_TX_THRESHOLD_256BYTES/
171                          ENET_TX_THRESHOLD_40BYTES/ ENET_TX_THRESHOLD_32BYTES/
172                          ENET_TX_THRESHOLD_24BYTES/ ENET_TX_THRESHOLD_16BYTES .
173                       DMA_OPTION related parameters:
174                       -  ENET_FLUSH_RXFRAME_ENABLE/ ENET_FLUSH_RXFRAME_DISABLE ;
175                       -  ENET_SECONDFRAME_OPT_ENABLE/ ENET_SECONDFRAME_OPT_DISABLE ;
176                       -  ENET_ENHANCED_DESCRIPTOR/ ENET_NORMAL_DESCRIPTOR .
177                       VLAN_OPTION related parameters:
178                       -  ENET_VLANTAGCOMPARISON_12BIT/ ENET_VLANTAGCOMPARISON_16BIT ;
179                       -  MAC_VLT_VLTI(regval) .
180                       FLOWCTL_OPTION related parameters:
181                       -  MAC_FCTL_PTM(regval) ;
182                       -  ENET_ZERO_QUANTA_PAUSE_ENABLE/ ENET_ZERO_QUANTA_PAUSE_DISABLE ;
183                       -  ENET_PAUSETIME_MINUS4/ ENET_PAUSETIME_MINUS28/
184                          ENET_PAUSETIME_MINUS144/ENET_PAUSETIME_MINUS256 ;
185                       -  ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT/ ENET_UNIQUE_PAUSEDETECT ;
186                       -  ENET_RX_FLOWCONTROL_ENABLE/ ENET_RX_FLOWCONTROL_DISABLE ;
187                       -  ENET_TX_FLOWCONTROL_ENABLE/ ENET_TX_FLOWCONTROL_DISABLE ;
188                       -  ENET_ACTIVE_THRESHOLD_256BYTES/ ENET_ACTIVE_THRESHOLD_512BYTES ;
189                       -  ENET_ACTIVE_THRESHOLD_768BYTES/ ENET_ACTIVE_THRESHOLD_1024BYTES ;
190                       -  ENET_ACTIVE_THRESHOLD_1280BYTES/ ENET_ACTIVE_THRESHOLD_1536BYTES ;
191                       -  ENET_ACTIVE_THRESHOLD_1792BYTES ;
192                       -  ENET_DEACTIVE_THRESHOLD_256BYTES/ ENET_DEACTIVE_THRESHOLD_512BYTES ;
193                       -  ENET_DEACTIVE_THRESHOLD_768BYTES/ ENET_DEACTIVE_THRESHOLD_1024BYTES ;
194                       -  ENET_DEACTIVE_THRESHOLD_1280BYTES/ ENET_DEACTIVE_THRESHOLD_1536BYTES ;
195                       -  ENET_DEACTIVE_THRESHOLD_1792BYTES .
196                       HASHH_OPTION related parameters:
197                       -  0x0~0xFFFF FFFFU
198                       HASHL_OPTION related parameters:
199                       -  0x0~0xFFFF FFFFU
200                       FILTER_OPTION related parameters:
201                       -  ENET_SRC_FILTER_NORMAL_ENABLE/ ENET_SRC_FILTER_INVERSE_ENABLE/
202                          ENET_SRC_FILTER_DISABLE ;
203                       -  ENET_DEST_FILTER_INVERSE_ENABLE/ ENET_DEST_FILTER_INVERSE_DISABLE ;
204                       -  ENET_MULTICAST_FILTER_HASH_OR_PERFECT/ ENET_MULTICAST_FILTER_HASH/
205                          ENET_MULTICAST_FILTER_PERFECT/ ENET_MULTICAST_FILTER_NONE ;
206                       -  ENET_UNICAST_FILTER_EITHER/ ENET_UNICAST_FILTER_HASH/
207                          ENET_UNICAST_FILTER_PERFECT ;
208                       -  ENET_PCFRM_PREVENT_ALL/ ENET_PCFRM_PREVENT_PAUSEFRAME/
209                          ENET_PCFRM_FORWARD_ALL/ ENET_PCFRM_FORWARD_FILTERED .
210                       HALFDUPLEX_OPTION related parameters:
211                       -  ENET_CARRIERSENSE_ENABLE/ ENET_CARRIERSENSE_DISABLE ;
212                       -  ENET_RECEIVEOWN_ENABLE/ ENET_RECEIVEOWN_DISABLE ;
213                       -  ENET_RETRYTRANSMISSION_ENABLE/ ENET_RETRYTRANSMISSION_DISABLE ;
214                       -  ENET_BACKOFFLIMIT_10/ ENET_BACKOFFLIMIT_8/
215                          ENET_BACKOFFLIMIT_4/ ENET_BACKOFFLIMIT_1 ;
216                       -  ENET_DEFERRALCHECK_ENABLE/ ENET_DEFERRALCHECK_DISABLE .
217                       TIMER_OPTION related parameters:
218                       -  ENET_WATCHDOG_ENABLE/ ENET_WATCHDOG_DISABLE ;
219                       -  ENET_JABBER_ENABLE/ ENET_JABBER_DISABLE ;
220                       INTERFRAMEGAP_OPTION related parameters:
221                       -  ENET_INTERFRAMEGAP_96BIT/ ENET_INTERFRAMEGAP_88BIT/
222                          ENET_INTERFRAMEGAP_80BIT/ ENET_INTERFRAMEGAP_72BIT/
223                          ENET_INTERFRAMEGAP_64BIT/ ENET_INTERFRAMEGAP_56BIT/
224                          ENET_INTERFRAMEGAP_48BIT/ ENET_INTERFRAMEGAP_40BIT .
225     \param[out] none
226     \retval     none
227 */
enet_initpara_config(enet_option_enum option,uint32_t para)228 void enet_initpara_config(enet_option_enum option, uint32_t para)
229 {
230     switch(option) {
231     case FORWARD_OPTION:
232         /* choose to configure forward_frame, and save the configuration parameters */
233         enet_initpara.option_enable |= (uint32_t)FORWARD_OPTION;
234         enet_initpara.forward_frame = para;
235         break;
236     case DMABUS_OPTION:
237         /* choose to configure dmabus_mode, and save the configuration parameters */
238         enet_initpara.option_enable |= (uint32_t)DMABUS_OPTION;
239         enet_initpara.dmabus_mode = para;
240         break;
241     case DMA_MAXBURST_OPTION:
242         /* choose to configure dma_maxburst, and save the configuration parameters */
243         enet_initpara.option_enable |= (uint32_t)DMA_MAXBURST_OPTION;
244         enet_initpara.dma_maxburst = para;
245         break;
246     case DMA_ARBITRATION_OPTION:
247         /* choose to configure dma_arbitration, and save the configuration parameters */
248         enet_initpara.option_enable |= (uint32_t)DMA_ARBITRATION_OPTION;
249         enet_initpara.dma_arbitration = para;
250         break;
251     case STORE_OPTION:
252         /* choose to configure store_forward_mode, and save the configuration parameters */
253         enet_initpara.option_enable |= (uint32_t)STORE_OPTION;
254         enet_initpara.store_forward_mode = para;
255         break;
256     case DMA_OPTION:
257         /* choose to configure dma_function, and save the configuration parameters */
258         enet_initpara.option_enable |= (uint32_t)DMA_OPTION;
259 
260 #ifndef SELECT_DESCRIPTORS_ENHANCED_MODE
261         para &= ~ENET_ENHANCED_DESCRIPTOR;
262 #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
263 
264         enet_initpara.dma_function = para;
265         break;
266     case VLAN_OPTION:
267         /* choose to configure vlan_config, and save the configuration parameters */
268         enet_initpara.option_enable |= (uint32_t)VLAN_OPTION;
269         enet_initpara.vlan_config = para;
270         break;
271     case FLOWCTL_OPTION:
272         /* choose to configure flow_control, and save the configuration parameters */
273         enet_initpara.option_enable |= (uint32_t)FLOWCTL_OPTION;
274         enet_initpara.flow_control = para;
275         break;
276     case HASHH_OPTION:
277         /* choose to configure hashtable_high, and save the configuration parameters */
278         enet_initpara.option_enable |= (uint32_t)HASHH_OPTION;
279         enet_initpara.hashtable_high = para;
280         break;
281     case HASHL_OPTION:
282         /* choose to configure hashtable_low, and save the configuration parameters */
283         enet_initpara.option_enable |= (uint32_t)HASHL_OPTION;
284         enet_initpara.hashtable_low = para;
285         break;
286     case FILTER_OPTION:
287         /* choose to configure framesfilter_mode, and save the configuration parameters */
288         enet_initpara.option_enable |= (uint32_t)FILTER_OPTION;
289         enet_initpara.framesfilter_mode = para;
290         break;
291     case HALFDUPLEX_OPTION:
292         /* choose to configure halfduplex_param, and save the configuration parameters */
293         enet_initpara.option_enable |= (uint32_t)HALFDUPLEX_OPTION;
294         enet_initpara.halfduplex_param = para;
295         break;
296     case TIMER_OPTION:
297         /* choose to configure timer_config, and save the configuration parameters */
298         enet_initpara.option_enable |= (uint32_t)TIMER_OPTION;
299         enet_initpara.timer_config = para;
300         break;
301     case INTERFRAMEGAP_OPTION:
302         /* choose to configure interframegap, and save the configuration parameters */
303         enet_initpara.option_enable |= (uint32_t)INTERFRAMEGAP_OPTION;
304         enet_initpara.interframegap = para;
305         break;
306     default:
307         break;
308     }
309 }
310 
311 /*!
312     \brief    initialize ENET peripheral with generally concerned parameters and the less cared
313                 parameters
314     \param[in]  mediamode: PHY mode and mac loopback configurations, refer to enet_mediamode_enum
315                 only one parameter can be selected which is shown as below
316       \arg        ENET_AUTO_NEGOTIATION: PHY auto negotiation
317       \arg        ENET_100M_FULLDUPLEX: 100Mbit/s, full-duplex
318       \arg        ENET_100M_HALFDUPLEX: 100Mbit/s, half-duplex
319       \arg        ENET_10M_FULLDUPLEX: 10Mbit/s, full-duplex
320       \arg        ENET_10M_HALFDUPLEX: 10Mbit/s, half-duplex
321       \arg        ENET_LOOPBACKMODE: MAC in loopback mode at the MII
322     \param[in]  checksum: IP frame checksum offload function, refer to enet_mediamode_enum
323                 only one parameter can be selected which is shown as below
324       \arg        ENET_NO_AUTOCHECKSUM: disable IP frame checksum function
325       \arg        ENET_AUTOCHECKSUM_DROP_FAILFRAMES: enable IP frame checksum function
326       \arg        ENET_AUTOCHECKSUM_ACCEPT_FAILFRAMES: enable IP frame checksum function, and the received frame
327                                                        with only payload error but no other errors will not be dropped
328     \param[in]  recept: frame filter function, refer to enet_frmrecept_enum
329                 only one parameter can be selected which is shown as below
330       \arg        ENET_PROMISCUOUS_MODE: promiscuous mode enabled
331       \arg        ENET_RECEIVEALL: all received frame are forwarded to application
332       \arg        ENET_BROADCAST_FRAMES_PASS: the address filters pass all received broadcast frames
333       \arg        ENET_BROADCAST_FRAMES_DROP: the address filters filter all incoming broadcast frames
334     \param[out] none
335     \retval     ErrStatus: ERROR or SUCCESS
336 */
enet_init(enet_mediamode_enum mediamode,enet_chksumconf_enum checksum,enet_frmrecept_enum recept)337 ErrStatus enet_init(enet_mediamode_enum mediamode, enet_chksumconf_enum checksum, enet_frmrecept_enum recept)
338 {
339     uint32_t reg_value = 0U, reg_temp = 0U, temp = 0U;
340     uint32_t media_temp = 0U;
341     uint32_t timeout = 0U;
342     uint16_t phy_value = 0U;
343     ErrStatus phy_state = ERROR, enet_state = ERROR;
344 
345     /* PHY interface configuration, configure SMI clock and reset PHY chip */
346     if(ERROR == enet_phy_config()) {
347         _ENET_DELAY_(PHY_RESETDELAY);
348         if(ERROR == enet_phy_config()) {
349             return enet_state;
350         }
351     }
352     /* initialize ENET peripheral with generally concerned parameters */
353     enet_default_init();
354 
355     /* 1st, configure mediamode */
356     media_temp = (uint32_t)mediamode;
357     /* if is PHY auto negotiation */
358     if((uint32_t)ENET_AUTO_NEGOTIATION == media_temp) {
359         /* wait for PHY_LINKED_STATUS bit be set */
360         do {
361             enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
362             phy_value &= PHY_LINKED_STATUS;
363             timeout++;
364         } while((RESET == phy_value) && (timeout < PHY_READ_TO));
365         /* return ERROR due to timeout */
366         if(PHY_READ_TO == timeout) {
367             return enet_state;
368         }
369         /* reset timeout counter */
370         timeout = 0U;
371 
372         /* enable auto-negotiation */
373         phy_value = PHY_AUTONEGOTIATION;
374         phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
375         if(!phy_state) {
376             /* return ERROR due to write timeout */
377             return enet_state;
378         }
379 
380         /* wait for the PHY_AUTONEGO_COMPLETE bit be set */
381         do {
382             enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BSR, &phy_value);
383             phy_value &= PHY_AUTONEGO_COMPLETE;
384             timeout++;
385         } while((RESET == phy_value) && (timeout < (uint32_t)PHY_READ_TO));
386         /* return ERROR due to timeout */
387         if(PHY_READ_TO == timeout) {
388             return enet_state;
389         }
390         /* reset timeout counter */
391         timeout = 0U;
392 
393         /* read the result of the auto-negotiation */
394         enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_SR, &phy_value);
395         /* configure the duplex mode of MAC following the auto-negotiation result */
396         if((uint16_t)RESET != (phy_value & PHY_DUPLEX_STATUS)) {
397             media_temp = ENET_MODE_FULLDUPLEX;
398         } else {
399             media_temp = ENET_MODE_HALFDUPLEX;
400         }
401         /* configure the communication speed of MAC following the auto-negotiation result */
402         if((uint16_t)RESET != (phy_value & PHY_SPEED_STATUS)) {
403             media_temp |= ENET_SPEEDMODE_10M;
404         } else {
405             media_temp |= ENET_SPEEDMODE_100M;
406         }
407     } else {
408         phy_value = (uint16_t)((media_temp & ENET_MAC_CFG_DPM) >> 3);
409         phy_value |= (uint16_t)((media_temp & ENET_MAC_CFG_SPD) >> 1);
410         phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value);
411         if(!phy_state) {
412             /* return ERROR due to write timeout */
413             return enet_state;
414         }
415         /* PHY configuration need some time */
416         _ENET_DELAY_(PHY_CONFIGDELAY);
417     }
418     /* after configuring the PHY, use mediamode to configure registers */
419     reg_value = ENET_MAC_CFG;
420     /* configure ENET_MAC_CFG register */
421     reg_value &= (~(ENET_MAC_CFG_SPD | ENET_MAC_CFG_DPM | ENET_MAC_CFG_LBM));
422     reg_value |= media_temp;
423     ENET_MAC_CFG = reg_value;
424 
425 
426     /* 2st, configure checksum */
427     if(RESET != ((uint32_t)checksum & ENET_CHECKSUMOFFLOAD_ENABLE)) {
428         ENET_MAC_CFG |= ENET_CHECKSUMOFFLOAD_ENABLE;
429 
430         reg_value = ENET_DMA_CTL;
431         /* configure ENET_DMA_CTL register */
432         reg_value &= ~ENET_DMA_CTL_DTCERFD;
433         reg_value |= ((uint32_t)checksum & ENET_DMA_CTL_DTCERFD);
434         ENET_DMA_CTL = reg_value;
435     }
436 
437     /* 3rd, configure recept */
438     ENET_MAC_FRMF |= (uint32_t)recept;
439 
440     /* 4th, configure different function options */
441     /* configure forward_frame related registers */
442     if(RESET != (enet_initpara.option_enable & (uint32_t)FORWARD_OPTION)) {
443         reg_temp = enet_initpara.forward_frame;
444 
445         reg_value = ENET_MAC_CFG;
446         temp = reg_temp;
447         /* configure ENET_MAC_CFG register */
448         reg_value &= (~(ENET_MAC_CFG_TFCD | ENET_MAC_CFG_APCD));
449         temp &= (ENET_MAC_CFG_TFCD | ENET_MAC_CFG_APCD);
450         reg_value |= temp;
451         ENET_MAC_CFG = reg_value;
452 
453         reg_value = ENET_DMA_CTL;
454         temp = reg_temp;
455         /* configure ENET_DMA_CTL register */
456         reg_value &= (~(ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF));
457         temp &= ((ENET_DMA_CTL_FERF | ENET_DMA_CTL_FUF) << 2);
458         reg_value |= (temp >> 2);
459         ENET_DMA_CTL = reg_value;
460     }
461 
462     /* configure dmabus_mode related registers */
463     if(RESET != (enet_initpara.option_enable & (uint32_t)DMABUS_OPTION)) {
464         temp = enet_initpara.dmabus_mode;
465 
466         reg_value = ENET_DMA_BCTL;
467         /* configure ENET_DMA_BCTL register */
468         reg_value &= ~(ENET_DMA_BCTL_AA | ENET_DMA_BCTL_FB \
469                        | ENET_DMA_BCTL_FPBL | ENET_DMA_BCTL_MB);
470         reg_value |= temp;
471         ENET_DMA_BCTL = reg_value;
472     }
473 
474     /* configure dma_maxburst related registers */
475     if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_MAXBURST_OPTION)) {
476         temp = enet_initpara.dma_maxburst;
477 
478         reg_value = ENET_DMA_BCTL;
479         /* configure ENET_DMA_BCTL register */
480         reg_value &= ~(ENET_DMA_BCTL_RXDP | ENET_DMA_BCTL_PGBL | ENET_DMA_BCTL_UIP);
481         reg_value |= temp;
482         ENET_DMA_BCTL = reg_value;
483     }
484 
485     /* configure dma_arbitration related registers */
486     if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_ARBITRATION_OPTION)) {
487         temp = enet_initpara.dma_arbitration;
488 
489         reg_value = ENET_DMA_BCTL;
490         /* configure ENET_DMA_BCTL register */
491         reg_value &= ~(ENET_DMA_BCTL_RTPR | ENET_DMA_BCTL_DAB);
492         reg_value |= temp;
493         ENET_DMA_BCTL = reg_value;
494     }
495 
496     /* configure store_forward_mode related registers */
497     if(RESET != (enet_initpara.option_enable & (uint32_t)STORE_OPTION)) {
498         temp = enet_initpara.store_forward_mode;
499 
500         reg_value = ENET_DMA_CTL;
501         /* configure ENET_DMA_CTL register */
502         reg_value &= ~(ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD | ENET_DMA_CTL_RTHC | ENET_DMA_CTL_TTHC);
503         reg_value |= temp;
504         ENET_DMA_CTL = reg_value;
505     }
506 
507     /* configure dma_function related registers */
508     if(RESET != (enet_initpara.option_enable & (uint32_t)DMA_OPTION)) {
509         reg_temp = enet_initpara.dma_function;
510 
511         reg_value = ENET_DMA_CTL;
512         temp = reg_temp;
513         /* configure ENET_DMA_CTL register */
514         reg_value &= (~(ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF));
515         temp &= (ENET_DMA_CTL_DAFRF | ENET_DMA_CTL_OSF);
516         reg_value |= temp;
517         ENET_DMA_CTL = reg_value;
518 
519         reg_value = ENET_DMA_BCTL;
520         temp = reg_temp;
521         /* configure ENET_DMA_BCTL register */
522         reg_value &= (~ENET_DMA_BCTL_DFM);
523         temp &= ENET_DMA_BCTL_DFM;
524         reg_value |= temp;
525         ENET_DMA_BCTL = reg_value;
526     }
527 
528     /* configure vlan_config related registers */
529     if(RESET != (enet_initpara.option_enable & (uint32_t)VLAN_OPTION)) {
530         reg_temp = enet_initpara.vlan_config;
531 
532         reg_value = ENET_MAC_VLT;
533         /* configure ENET_MAC_VLT register */
534         reg_value &= ~(ENET_MAC_VLT_VLTI | ENET_MAC_VLT_VLTC);
535         reg_value |= reg_temp;
536         ENET_MAC_VLT = reg_value;
537     }
538 
539     /* configure flow_control related registers */
540     if(RESET != (enet_initpara.option_enable & (uint32_t)FLOWCTL_OPTION)) {
541         reg_temp = enet_initpara.flow_control;
542 
543         reg_value = ENET_MAC_FCTL;
544         temp = reg_temp;
545         /* configure ENET_MAC_FCTL register */
546         reg_value &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_DZQP | ENET_MAC_FCTL_PLTS \
547                        | ENET_MAC_FCTL_UPFDT | ENET_MAC_FCTL_RFCEN | ENET_MAC_FCTL_TFCEN);
548         temp &= (ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_DZQP | ENET_MAC_FCTL_PLTS \
549                  | ENET_MAC_FCTL_UPFDT | ENET_MAC_FCTL_RFCEN | ENET_MAC_FCTL_TFCEN);
550         reg_value |= temp;
551         ENET_MAC_FCTL = reg_value;
552 
553         reg_value = ENET_MAC_FCTH;
554         temp = reg_temp;
555         /* configure ENET_MAC_FCTH register */
556         reg_value &= ~(ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD);
557         temp &= ((ENET_MAC_FCTH_RFA | ENET_MAC_FCTH_RFD) << 8);
558         reg_value |= (temp >> 8);
559         ENET_MAC_FCTH = reg_value;
560     }
561 
562     /* configure hashtable_high related registers */
563     if(RESET != (enet_initpara.option_enable & (uint32_t)HASHH_OPTION)) {
564         ENET_MAC_HLH = enet_initpara.hashtable_high;
565     }
566 
567     /* configure hashtable_low related registers */
568     if(RESET != (enet_initpara.option_enable & (uint32_t)HASHL_OPTION)) {
569         ENET_MAC_HLL = enet_initpara.hashtable_low;
570     }
571 
572     /* configure framesfilter_mode related registers */
573     if(RESET != (enet_initpara.option_enable & (uint32_t)FILTER_OPTION)) {
574         reg_temp = enet_initpara.framesfilter_mode;
575 
576         reg_value = ENET_MAC_FRMF;
577         /* configure ENET_MAC_FRMF register */
578         reg_value &= ~(ENET_MAC_FRMF_SAFLT | ENET_MAC_FRMF_SAIFLT | ENET_MAC_FRMF_DAIFLT \
579                        | ENET_MAC_FRMF_HMF | ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_MFD \
580                        | ENET_MAC_FRMF_HUF | ENET_MAC_FRMF_PCFRM);
581         reg_value |= reg_temp;
582         ENET_MAC_FRMF = reg_value;
583     }
584 
585     /* configure halfduplex_param related registers */
586     if(RESET != (enet_initpara.option_enable & (uint32_t)HALFDUPLEX_OPTION)) {
587         reg_temp = enet_initpara.halfduplex_param;
588 
589         reg_value = ENET_MAC_CFG;
590         /* configure ENET_MAC_CFG register */
591         reg_value &= ~(ENET_MAC_CFG_CSD | ENET_MAC_CFG_ROD | ENET_MAC_CFG_RTD \
592                        | ENET_MAC_CFG_BOL | ENET_MAC_CFG_DFC);
593         reg_value |= reg_temp;
594         ENET_MAC_CFG = reg_value;
595     }
596 
597     /* configure timer_config related registers */
598     if(RESET != (enet_initpara.option_enable & (uint32_t)TIMER_OPTION)) {
599         reg_temp = enet_initpara.timer_config;
600 
601         reg_value = ENET_MAC_CFG;
602         /* configure ENET_MAC_CFG register */
603         reg_value &= ~(ENET_MAC_CFG_WDD | ENET_MAC_CFG_JBD);
604         reg_value |= reg_temp;
605         ENET_MAC_CFG = reg_value;
606     }
607 
608     /* configure interframegap related registers */
609     if(RESET != (enet_initpara.option_enable & (uint32_t)INTERFRAMEGAP_OPTION)) {
610         reg_temp = enet_initpara.interframegap;
611 
612         reg_value = ENET_MAC_CFG;
613         /* configure ENET_MAC_CFG register */
614         reg_value &= ~ENET_MAC_CFG_IGBS;
615         reg_value |= reg_temp;
616         ENET_MAC_CFG = reg_value;
617     }
618 
619     enet_state = SUCCESS;
620     return enet_state;
621 }
622 
623 /*!
624     \brief    reset all core internal registers located in CLK_TX and CLK_RX
625     \param[in]  none
626     \param[out] none
627     \retval     ErrStatus: SUCCESS or ERROR
628 */
enet_software_reset(void)629 ErrStatus enet_software_reset(void)
630 {
631     uint32_t timeout = 0U;
632     ErrStatus enet_state = ERROR;
633     uint32_t dma_flag;
634 
635     /* reset all core internal registers located in CLK_TX and CLK_RX */
636     ENET_DMA_BCTL |= ENET_DMA_BCTL_SWR;
637 
638     /* wait for reset operation complete */
639     do {
640         dma_flag = (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR);
641         timeout++;
642     } while((RESET != dma_flag) && (ENET_DELAY_TO != timeout));
643 
644     /* reset operation complete */
645     if(RESET == (ENET_DMA_BCTL & ENET_DMA_BCTL_SWR)) {
646         enet_state = SUCCESS;
647     }
648 
649     return enet_state;
650 }
651 
652 /*!
653     \brief    check receive frame valid and return frame size
654     \param[in]  none
655     \param[out] none
656     \retval     size of received frame: 0x0 - 0x3FFF
657 */
enet_rxframe_size_get(void)658 uint32_t enet_rxframe_size_get(void)
659 {
660     uint32_t size = 0U;
661     uint32_t status;
662 
663     /* get rdes0 information of current RxDMA descriptor */
664     status = dma_current_rxdesc->status;
665 
666     /* if the desciptor is owned by DMA */
667     if((uint32_t)RESET != (status & ENET_RDES0_DAV)) {
668         return 0U;
669     }
670 
671     /* if has any error, or the frame uses two or more descriptors */
672     if((((uint32_t)RESET) != (status & ENET_RDES0_ERRS)) ||
673             (((uint32_t)RESET) == (status & ENET_RDES0_LDES)) ||
674             (((uint32_t)RESET) == (status & ENET_RDES0_FDES))) {
675         /* drop current receive frame */
676         enet_rxframe_drop();
677 
678         return 1U;
679     }
680 #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
681     /* if is an ethernet-type frame, and IP frame payload error occurred */
682     if(((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FRMT) &&
683             ((uint32_t)RESET) != (dma_current_rxdesc->extended_status & ENET_RDES4_IPPLDERR)) {
684         /* drop current receive frame */
685         enet_rxframe_drop();
686 
687         return 1U;
688     }
689 #else
690     /* if is an ethernet-type frame, and IP frame payload error occurred */
691     if((((uint32_t)RESET) != (status & ENET_RDES0_FRMT)) &&
692             (((uint32_t)RESET) != (status & ENET_RDES0_PCERR))) {
693         /* drop current receive frame */
694         enet_rxframe_drop();
695 
696         return 1U;
697     }
698 #endif
699     /* if CPU owns current descriptor, no error occured, the frame uses only one descriptor */
700     if((((uint32_t)RESET) == (status & ENET_RDES0_DAV)) &&
701             (((uint32_t)RESET) == (status & ENET_RDES0_ERRS)) &&
702             (((uint32_t)RESET) != (status & ENET_RDES0_LDES)) &&
703             (((uint32_t)RESET) != (status & ENET_RDES0_FDES))) {
704         /* get the size of the received data including CRC */
705         size = GET_RDES0_FRML(status);
706         /* substract the CRC size */
707         size = size - 4U;
708 
709         /* if is a type frame, and CRC is not included in forwarding frame */
710         if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (status & ENET_RDES0_FRMT))) {
711             size = size + 4U;
712         }
713     } else {
714         enet_unknow_err++;
715         enet_rxframe_drop();
716 
717         return 1U;
718     }
719 
720     /* return packet size */
721     return size;
722 }
723 
724 /*!
725     \brief    initialize the DMA Tx/Rx descriptors's parameters in chain mode
726     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
727                 only one parameter can be selected which is shown as below
728       \arg        ENET_DMA_TX: DMA Tx descriptors
729       \arg        ENET_DMA_RX: DMA Rx descriptors
730     \param[out] none
731     \retval     none
732 */
enet_descriptors_chain_init(enet_dmadirection_enum direction)733 void enet_descriptors_chain_init(enet_dmadirection_enum direction)
734 {
735     uint32_t num = 0U, count = 0U, maxsize = 0U;
736     uint32_t desc_status = 0U, desc_bufsize = 0U;
737     enet_descriptors_struct *desc, *desc_tab;
738     uint8_t *buf;
739 
740     /* if want to initialize DMA Tx descriptors */
741     if(ENET_DMA_TX == direction) {
742         /* save a copy of the DMA Tx descriptors */
743         desc_tab = txdesc_tab;
744         buf = &tx_buff[0][0];
745         count = ENET_TXBUF_NUM;
746         maxsize = ENET_TXBUF_SIZE;
747 
748         /* select chain mode */
749         desc_status = ENET_TDES0_TCHM;
750 
751         /* configure DMA Tx descriptor table address register */
752         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
753         dma_current_txdesc = desc_tab;
754     } else {
755         /* if want to initialize DMA Rx descriptors */
756         /* save a copy of the DMA Rx descriptors */
757         desc_tab = rxdesc_tab;
758         buf = &rx_buff[0][0];
759         count = ENET_RXBUF_NUM;
760         maxsize = ENET_RXBUF_SIZE;
761 
762         /* enable receiving */
763         desc_status = ENET_RDES0_DAV;
764         /* select receive chained mode and set buffer1 size */
765         desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE;
766 
767         /* configure DMA Rx descriptor table address register */
768         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
769         dma_current_rxdesc = desc_tab;
770     }
771     dma_current_ptp_rxdesc = NULL;
772     dma_current_ptp_txdesc = NULL;
773 
774     /* configure each descriptor */
775     for(num = 0U; num < count; num++) {
776         /* get the pointer to the next descriptor of the descriptor table */
777         desc = desc_tab + num;
778 
779         /* configure descriptors */
780         desc->status = desc_status;
781         desc->control_buffer_size = desc_bufsize;
782         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
783 
784         /* if is not the last descriptor */
785         if(num < (count - 1U)) {
786             /* configure the next descriptor address */
787             desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U);
788         } else {
789             /* when it is the last descriptor, the next descriptor address
790             equals to first descriptor address in descriptor table */
791             desc->buffer2_next_desc_addr = (uint32_t) desc_tab;
792         }
793     }
794 }
795 
796 /*!
797     \brief    initialize the DMA Tx/Rx descriptors's parameters in ring mode
798     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
799                 only one parameter can be selected which is shown as below
800       \arg        ENET_DMA_TX: DMA Tx descriptors
801       \arg        ENET_DMA_RX: DMA Rx descriptors
802     \param[out] none
803     \retval     none
804 */
enet_descriptors_ring_init(enet_dmadirection_enum direction)805 void enet_descriptors_ring_init(enet_dmadirection_enum direction)
806 {
807     uint32_t num = 0U, count = 0U, maxsize = 0U;
808     uint32_t desc_status = 0U, desc_bufsize = 0U;
809     enet_descriptors_struct *desc;
810     enet_descriptors_struct *desc_tab;
811     uint8_t *buf;
812 
813     /* configure descriptor skip length */
814     ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL;
815     ENET_DMA_BCTL |= DMA_BCTL_DPSL(0);
816 
817     /* if want to initialize DMA Tx descriptors */
818     if(ENET_DMA_TX == direction) {
819         /* save a copy of the DMA Tx descriptors */
820         desc_tab = txdesc_tab;
821         buf = &tx_buff[0][0];
822         count = ENET_TXBUF_NUM;
823         maxsize = ENET_TXBUF_SIZE;
824 
825         /* configure DMA Tx descriptor table address register */
826         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
827         dma_current_txdesc = desc_tab;
828     } else {
829         /* if want to initialize DMA Rx descriptors */
830         /* save a copy of the DMA Rx descriptors */
831         desc_tab = rxdesc_tab;
832         buf = &rx_buff[0][0];
833         count = ENET_RXBUF_NUM;
834         maxsize = ENET_RXBUF_SIZE;
835 
836         /* enable receiving */
837         desc_status = ENET_RDES0_DAV;
838         /* set buffer1 size */
839         desc_bufsize = ENET_RXBUF_SIZE;
840 
841         /* configure DMA Rx descriptor table address register */
842         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
843         dma_current_rxdesc = desc_tab;
844     }
845     dma_current_ptp_rxdesc = NULL;
846     dma_current_ptp_txdesc = NULL;
847 
848     /* configure each descriptor */
849     for(num = 0U; num < count; num++) {
850         /* get the pointer to the next descriptor of the descriptor table */
851         desc = desc_tab + num;
852 
853         /* configure descriptors */
854         desc->status = desc_status;
855         desc->control_buffer_size = desc_bufsize;
856         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
857 
858         /* when it is the last descriptor */
859         if(num == (count - 1U)) {
860             if(ENET_DMA_TX == direction) {
861                 /* configure transmit end of ring mode */
862                 desc->status |= ENET_TDES0_TERM;
863             } else {
864                 /* configure receive end of ring mode */
865                 desc->control_buffer_size |= ENET_RDES1_RERM;
866             }
867         }
868     }
869 }
870 
871 /*!
872     \brief    handle current received frame data to application buffer
873     \param[in]  bufsize: the size of buffer which is the parameter in function
874     \param[out] buffer: pointer to the received frame data
875                 note -- if the input is NULL, user should copy data in application by himself
876     \retval     ErrStatus: SUCCESS or ERROR
877 */
enet_frame_receive(uint8_t * buffer,uint32_t bufsize)878 ErrStatus enet_frame_receive(uint8_t *buffer, uint32_t bufsize)
879 {
880     uint32_t offset = 0U, size = 0U;
881 
882     /* the descriptor is busy due to own by the DMA */
883     if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)) {
884         return ERROR;
885     }
886 
887 
888     /* if buffer pointer is null, indicates that users has copied data in application */
889     if(NULL != buffer) {
890         /* if no error occurs, and the frame uses only one descriptor */
891         if((((uint32_t)RESET) == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) &&
892                 (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_LDES)) &&
893                 (((uint32_t)RESET) != (dma_current_rxdesc->status & ENET_RDES0_FDES))) {
894             /* get the frame length except CRC */
895             size = GET_RDES0_FRML(dma_current_rxdesc->status);
896             size = size - 4U;
897 
898             /* if is a type frame, and CRC is not included in forwarding frame */
899             if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))) {
900                 size = size + 4U;
901             }
902 
903             /* to avoid situation that the frame size exceeds the buffer length */
904             if(size > bufsize) {
905                 return ERROR;
906             }
907 
908             /* copy data from Rx buffer to application buffer */
909             for(offset = 0U; offset < size; offset++) {
910                 (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_rxdesc->buffer1_addr) + offset));
911             }
912 
913         } else {
914             /* return ERROR */
915             return ERROR;
916         }
917     }
918     /* enable reception, descriptor is owned by DMA */
919     dma_current_rxdesc->status = ENET_RDES0_DAV;
920 
921     /* check Rx buffer unavailable flag status */
922     if((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) {
923         /* clear RBU flag */
924         ENET_DMA_STAT = ENET_DMA_STAT_RBU;
925         /* resume DMA reception by writing to the RPEN register*/
926         ENET_DMA_RPEN = 0U;
927     }
928 
929     /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */
930     /* chained mode */
931     if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) {
932         dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_rxdesc->buffer2_next_desc_addr);
933     } else {
934         /* ring mode */
935         if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) {
936             /* if is the last descriptor in table, the next descriptor is the table header */
937             dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR);
938         } else {
939             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
940             dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)));
941         }
942     }
943 
944     return SUCCESS;
945 }
946 
947 /*!
948     \brief    handle application buffer data to transmit it
949     \param[in]  buffer: pointer to the frame data to be transmitted,
950                 note -- if the input is NULL, user should handle the data in application by himself
951     \param[in]  length: the length of frame data to be transmitted
952     \param[out] none
953     \retval     ErrStatus: SUCCESS or ERROR
954 */
enet_frame_transmit(uint8_t * buffer,uint32_t length)955 ErrStatus enet_frame_transmit(uint8_t *buffer, uint32_t length)
956 {
957     uint32_t offset = 0U;
958     uint32_t dma_tbu_flag, dma_tu_flag;
959 
960     /* the descriptor is busy due to own by the DMA */
961     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) {
962         return ERROR;
963     }
964 
965     /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */
966     if(length > ENET_MAX_FRAME_SIZE) {
967         return ERROR;
968     }
969 
970     /* if buffer pointer is null, indicates that users has handled data in application */
971     if(NULL != buffer) {
972         /* copy frame data from application buffer to Tx buffer */
973         for(offset = 0U; offset < length; offset++) {
974             (*(__IO uint8_t *)(uint32_t)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset));
975         }
976     }
977 
978     /* set the frame length */
979     dma_current_txdesc->control_buffer_size = length;
980     /* set the segment of frame, frame is transmitted in one descriptor */
981     dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG;
982     /* enable the DMA transmission */
983     dma_current_txdesc->status |= ENET_TDES0_DAV;
984 
985     /* check Tx buffer unavailable flag status */
986     dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU);
987     dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU);
988 
989     if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)) {
990         /* clear TBU and TU flag */
991         ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag);
992         /* resume DMA transmission by writing to the TPEN register*/
993         ENET_DMA_TPEN = 0U;
994     }
995 
996     /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/
997     /* chained mode */
998     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)) {
999         dma_current_txdesc = (enet_descriptors_struct *)(dma_current_txdesc->buffer2_next_desc_addr);
1000     } else {
1001         /* ring mode */
1002         if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)) {
1003             /* if is the last descriptor in table, the next descriptor is the table header */
1004             dma_current_txdesc = (enet_descriptors_struct *)(ENET_DMA_TDTADDR);
1005         } else {
1006             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
1007             dma_current_txdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + (GET_DMA_BCTL_DPSL(ENET_DMA_BCTL)));
1008         }
1009     }
1010 
1011     return SUCCESS;
1012 }
1013 
1014 /*!
1015     \brief    configure the transmit IP frame checksum offload calculation and insertion
1016     \param[in]  desc: the descriptor pointer which users want to configure, refer to enet_descriptors_struct
1017     \param[in]  checksum: IP frame checksum configuration
1018                 only one parameter can be selected which is shown as below
1019       \arg        ENET_CHECKSUM_DISABLE: checksum insertion disabled
1020       \arg        ENET_CHECKSUM_IPV4HEADER: only IP header checksum calculation and insertion are enabled
1021       \arg        ENET_CHECKSUM_TCPUDPICMP_SEGMENT: TCP/UDP/ICMP checksum insertion calculated but pseudo-header
1022       \arg        ENET_CHECKSUM_TCPUDPICMP_FULL: TCP/UDP/ICMP checksum insertion fully calculated
1023     \param[out] none
1024     \retval     none
1025 */
enet_transmit_checksum_config(enet_descriptors_struct * desc,uint32_t checksum)1026 void enet_transmit_checksum_config(enet_descriptors_struct *desc, uint32_t checksum)
1027 {
1028     desc->status &= ~ENET_TDES0_CM;
1029     desc->status |= checksum;
1030 }
1031 
1032 /*!
1033     \brief    ENET Tx and Rx function enable (include MAC and DMA module)
1034     \param[in]  none
1035     \param[out] none
1036     \retval     none
1037 */
enet_enable(void)1038 void enet_enable(void)
1039 {
1040     enet_tx_enable();
1041     enet_rx_enable();
1042 }
1043 
1044 /*!
1045     \brief    ENET Tx and Rx function disable (include MAC and DMA module)
1046     \param[in]  none
1047     \param[out] none
1048     \retval     none
1049 */
enet_disable(void)1050 void enet_disable(void)
1051 {
1052     enet_tx_disable();
1053     enet_rx_disable();
1054 }
1055 
1056 /*!
1057     \brief    configure MAC address
1058     \param[in]  mac_addr: select which MAC address will be set, refer to enet_macaddress_enum
1059                 only one parameter can be selected which is shown as below
1060       \arg        ENET_MAC_ADDRESS0: set MAC address 0 filter
1061       \arg        ENET_MAC_ADDRESS1: set MAC address 1 filter
1062       \arg        ENET_MAC_ADDRESS2: set MAC address 2 filter
1063       \arg        ENET_MAC_ADDRESS3: set MAC address 3 filter
1064     \param[in]  paddr: the buffer pointer which stores the MAC address
1065                   (little-ending store, such as MAC address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa})
1066     \param[out] none
1067     \retval     none
1068 */
enet_mac_address_set(enet_macaddress_enum mac_addr,uint8_t paddr[])1069 void enet_mac_address_set(enet_macaddress_enum mac_addr, uint8_t paddr[])
1070 {
1071     REG32(ENET_ADDRH_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRH(paddr);
1072     REG32(ENET_ADDRL_BASE + (uint32_t)mac_addr) = ENET_SET_MACADDRL(paddr);
1073 }
1074 
1075 /*!
1076     \brief    get MAC address
1077     \param[in]  mac_addr: select which MAC address will be get, refer to enet_macaddress_enum
1078                 only one parameter can be selected which is shown as below
1079       \arg        ENET_MAC_ADDRESS0: get MAC address 0 filter
1080       \arg        ENET_MAC_ADDRESS1: get MAC address 1 filter
1081       \arg        ENET_MAC_ADDRESS2: get MAC address 2 filter
1082       \arg        ENET_MAC_ADDRESS3: get MAC address 3 filter
1083     \param[out] paddr: the buffer pointer which is stored the MAC address
1084                   (little-ending store, such as mac address is aa:bb:cc:dd:ee:22, the buffer is {22, ee, dd, cc, bb, aa})
1085     \retval     none
1086 */
enet_mac_address_get(enet_macaddress_enum mac_addr,uint8_t paddr[])1087 void enet_mac_address_get(enet_macaddress_enum mac_addr, uint8_t paddr[])
1088 {
1089     paddr[0] = ENET_GET_MACADDR(mac_addr, 0U);
1090     paddr[1] = ENET_GET_MACADDR(mac_addr, 1U);
1091     paddr[2] = ENET_GET_MACADDR(mac_addr, 2U);
1092     paddr[3] = ENET_GET_MACADDR(mac_addr, 3U);
1093     paddr[4] = ENET_GET_MACADDR(mac_addr, 4U);
1094     paddr[5] = ENET_GET_MACADDR(mac_addr, 5U);
1095 }
1096 
1097 /*!
1098     \brief    get the ENET MAC/MSC/PTP/DMA status flag
1099     \param[in]  enet_flag: ENET status flag, refer to enet_flag_enum,
1100                 only one parameter can be selected which is shown as below
1101       \arg        ENET_MAC_FLAG_MPKR: magic packet received flag
1102       \arg        ENET_MAC_FLAG_WUFR: wakeup frame received flag
1103       \arg        ENET_MAC_FLAG_FLOWCONTROL: flow control status flag
1104       \arg        ENET_MAC_FLAG_WUM: WUM status flag
1105       \arg        ENET_MAC_FLAG_MSC: MSC status flag
1106       \arg        ENET_MAC_FLAG_MSCR: MSC receive status flag
1107       \arg        ENET_MAC_FLAG_MSCT: MSC transmit status flag
1108       \arg        ENET_MAC_FLAG_TMST: time stamp trigger status flag
1109       \arg        ENET_PTP_FLAG_TSSCO: timestamp second counter overflow flag
1110       \arg        ENET_PTP_FLAG_TTM: target time match flag
1111       \arg        ENET_MSC_FLAG_RFCE: received frames CRC error flag
1112       \arg        ENET_MSC_FLAG_RFAE: received frames alignment error flag
1113       \arg        ENET_MSC_FLAG_RGUF: received good unicast frames flag
1114       \arg        ENET_MSC_FLAG_TGFSC: transmitted good frames single collision flag
1115       \arg        ENET_MSC_FLAG_TGFMSC: transmitted good frames more single collision flag
1116       \arg        ENET_MSC_FLAG_TGF: transmitted good frames flag
1117       \arg        ENET_DMA_FLAG_TS: transmit status flag
1118       \arg        ENET_DMA_FLAG_TPS: transmit process stopped status flag
1119       \arg        ENET_DMA_FLAG_TBU: transmit buffer unavailable status flag
1120       \arg        ENET_DMA_FLAG_TJT: transmit jabber timeout status flag
1121       \arg        ENET_DMA_FLAG_RO: receive overflow status flag
1122       \arg        ENET_DMA_FLAG_TU: transmit underflow status flag
1123       \arg        ENET_DMA_FLAG_RS: receive status flag
1124       \arg        ENET_DMA_FLAG_RBU: receive buffer unavailable status flag
1125       \arg        ENET_DMA_FLAG_RPS: receive process stopped status flag
1126       \arg        ENET_DMA_FLAG_RWT: receive watchdog timeout status flag
1127       \arg        ENET_DMA_FLAG_ET: early transmit status flag
1128       \arg        ENET_DMA_FLAG_FBE: fatal bus error status flag
1129       \arg        ENET_DMA_FLAG_ER: early receive status flag
1130       \arg        ENET_DMA_FLAG_AI: abnormal interrupt summary flag
1131       \arg        ENET_DMA_FLAG_NI: normal interrupt summary flag
1132       \arg        ENET_DMA_FLAG_EB_DMA_ERROR: DMA error flag
1133       \arg        ENET_DMA_FLAG_EB_TRANSFER_ERROR: transfer error flag
1134       \arg        ENET_DMA_FLAG_EB_ACCESS_ERROR: access error flag
1135       \arg        ENET_DMA_FLAG_MSC: MSC status flag
1136       \arg        ENET_DMA_FLAG_WUM: WUM status flag
1137       \arg        ENET_DMA_FLAG_TST: timestamp trigger status flag
1138     \param[out] none
1139     \retval     FlagStatus: SET or RESET
1140 */
enet_flag_get(enet_flag_enum enet_flag)1141 FlagStatus enet_flag_get(enet_flag_enum enet_flag)
1142 {
1143     if(RESET != (ENET_REG_VAL(enet_flag) & BIT(ENET_BIT_POS(enet_flag)))) {
1144         return SET;
1145     } else {
1146         return RESET;
1147     }
1148 }
1149 
1150 /*!
1151     \brief    clear the ENET DMA status flag
1152     \param[in]  enet_flag: ENET DMA flag clear, refer to enet_flag_clear_enum
1153                 only one parameter can be selected which is shown as below
1154       \arg        ENET_DMA_FLAG_TS_CLR: transmit status flag clear
1155       \arg        ENET_DMA_FLAG_TPS_CLR: transmit process stopped status flag clear
1156       \arg        ENET_DMA_FLAG_TBU_CLR: transmit buffer unavailable status flag clear
1157       \arg        ENET_DMA_FLAG_TJT_CLR: transmit jabber timeout status flag clear
1158       \arg        ENET_DMA_FLAG_RO_CLR: receive overflow status flag clear
1159       \arg        ENET_DMA_FLAG_TU_CLR: transmit underflow status flag clear
1160       \arg        ENET_DMA_FLAG_RS_CLR: receive status flag clear
1161       \arg        ENET_DMA_FLAG_RBU_CLR: receive buffer unavailable status flag clear
1162       \arg        ENET_DMA_FLAG_RPS_CLR: receive process stopped status flag clear
1163       \arg        ENET_DMA_FLAG_RWT_CLR: receive watchdog timeout status flag clear
1164       \arg        ENET_DMA_FLAG_ET_CLR: early transmit status flag clear
1165       \arg        ENET_DMA_FLAG_FBE_CLR: fatal bus error status flag clear
1166       \arg        ENET_DMA_FLAG_ER_CLR: early receive status flag clear
1167       \arg        ENET_DMA_FLAG_AI_CLR: abnormal interrupt summary flag clear
1168       \arg        ENET_DMA_FLAG_NI_CLR: normal interrupt summary flag clear
1169     \param[out] none
1170     \retval     none
1171 */
enet_flag_clear(enet_flag_clear_enum enet_flag)1172 void enet_flag_clear(enet_flag_clear_enum enet_flag)
1173 {
1174     /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */
1175     ENET_REG_VAL(enet_flag) = BIT(ENET_BIT_POS(enet_flag));
1176 }
1177 
1178 /*!
1179     \brief    enable ENET MAC/MSC/DMA interrupt
1180     \param[in]  enet_int: ENET interrupt,, refer to enet_int_enum
1181                 only one parameter can be selected which is shown as below
1182       \arg        ENET_MAC_INT_WUMIM: WUM interrupt mask
1183       \arg        ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask
1184       \arg        ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask
1185       \arg        ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask
1186       \arg        ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask
1187       \arg        ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask
1188       \arg        ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask
1189       \arg        ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask
1190       \arg        ENET_DMA_INT_TIE: transmit interrupt enable
1191       \arg        ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable
1192       \arg        ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable
1193       \arg        ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable
1194       \arg        ENET_DMA_INT_ROIE: receive overflow interrupt enable
1195       \arg        ENET_DMA_INT_TUIE: transmit underflow interrupt enable
1196       \arg        ENET_DMA_INT_RIE: receive interrupt enable
1197       \arg        ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable
1198       \arg        ENET_DMA_INT_RPSIE: receive process stopped interrupt enable
1199       \arg        ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable
1200       \arg        ENET_DMA_INT_ETIE: early transmit interrupt enable
1201       \arg        ENET_DMA_INT_FBEIE: fatal bus error interrupt enable
1202       \arg        ENET_DMA_INT_ERIE: early receive interrupt enable
1203       \arg        ENET_DMA_INT_AIE: abnormal interrupt summary enable
1204       \arg        ENET_DMA_INT_NIE: normal interrupt summary enable
1205     \param[out] none
1206     \retval     none
1207 */
enet_interrupt_enable(enet_int_enum enet_int)1208 void enet_interrupt_enable(enet_int_enum enet_int)
1209 {
1210     if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)) {
1211         /* ENET_DMA_INTEN register interrupt */
1212         ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int));
1213     } else {
1214         /* other INTMSK register interrupt */
1215         ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int));
1216     }
1217 }
1218 
1219 /*!
1220     \brief    disable ENET MAC/MSC/DMA interrupt
1221     \param[in]  enet_int: ENET interrupt, refer to enet_int_enum
1222                 only one parameter can be selected which is shown as below
1223       \arg        ENET_MAC_INT_WUMIM: WUM interrupt mask
1224       \arg        ENET_MAC_INT_TMSTIM: timestamp trigger interrupt mask
1225       \arg        ENET_MSC_INT_RFCEIM: received frame CRC error interrupt mask
1226       \arg        ENET_MSC_INT_RFAEIM: received frames alignment error interrupt mask
1227       \arg        ENET_MSC_INT_RGUFIM: received good unicast frames interrupt mask
1228       \arg        ENET_MSC_INT_TGFSCIM: transmitted good frames single collision interrupt mask
1229       \arg        ENET_MSC_INT_TGFMSCIM: transmitted good frames more single collision interrupt mask
1230       \arg        ENET_MSC_INT_TGFIM: transmitted good frames interrupt mask
1231       \arg        ENET_DMA_INT_TIE: transmit interrupt enable
1232       \arg        ENET_DMA_INT_TPSIE: transmit process stopped interrupt enable
1233       \arg        ENET_DMA_INT_TBUIE: transmit buffer unavailable interrupt enable
1234       \arg        ENET_DMA_INT_TJTIE: transmit jabber timeout interrupt enable
1235       \arg        ENET_DMA_INT_ROIE: receive overflow interrupt enable
1236       \arg        ENET_DMA_INT_TUIE: transmit underflow interrupt enable
1237       \arg        ENET_DMA_INT_RIE: receive interrupt enable
1238       \arg        ENET_DMA_INT_RBUIE: receive buffer unavailable interrupt enable
1239       \arg        ENET_DMA_INT_RPSIE: receive process stopped interrupt enable
1240       \arg        ENET_DMA_INT_RWTIE: receive watchdog timeout interrupt enable
1241       \arg        ENET_DMA_INT_ETIE: early transmit interrupt enable
1242       \arg        ENET_DMA_INT_FBEIE: fatal bus error interrupt enable
1243       \arg        ENET_DMA_INT_ERIE: early receive interrupt enable
1244       \arg        ENET_DMA_INT_AIE: abnormal interrupt summary enable
1245       \arg        ENET_DMA_INT_NIE: normal interrupt summary enable
1246     \param[out] none
1247     \retval     none
1248 */
enet_interrupt_disable(enet_int_enum enet_int)1249 void enet_interrupt_disable(enet_int_enum enet_int)
1250 {
1251     if(DMA_INTEN_REG_OFFSET == ((uint32_t)enet_int >> 6)) {
1252         /* ENET_DMA_INTEN register interrupt */
1253         ENET_REG_VAL(enet_int) &= ~BIT(ENET_BIT_POS(enet_int));
1254     } else {
1255         /* other INTMSK register interrupt */
1256         ENET_REG_VAL(enet_int) |= BIT(ENET_BIT_POS(enet_int));
1257     }
1258 }
1259 
1260 /*!
1261     \brief    get ENET MAC/MSC/DMA interrupt flag
1262     \param[in]  int_flag: ENET interrupt flag, refer to enet_int_flag_enum
1263                 only one parameter can be selected which is shown as below
1264       \arg        ENET_MAC_INT_FLAG_WUM: WUM status flag
1265       \arg        ENET_MAC_INT_FLAG_MSC: MSC status flag
1266       \arg        ENET_MAC_INT_FLAG_MSCR: MSC receive status flag
1267       \arg        ENET_MAC_INT_FLAG_MSCT: MSC transmit status flag
1268       \arg        ENET_MAC_INT_FLAG_TMST: time stamp trigger status flag
1269       \arg        ENET_MSC_INT_FLAG_RFCE: received frames CRC error flag
1270       \arg        ENET_MSC_INT_FLAG_RFAE: received frames alignment error flag
1271       \arg        ENET_MSC_INT_FLAG_RGUF: received good unicast frames flag
1272       \arg        ENET_MSC_INT_FLAG_TGFSC: transmitted good frames single collision flag
1273       \arg        ENET_MSC_INT_FLAG_TGFMSC: transmitted good frames more single collision flag
1274       \arg        ENET_MSC_INT_FLAG_TGF: transmitted good frames flag
1275       \arg        ENET_DMA_INT_FLAG_TS: transmit status flag
1276       \arg        ENET_DMA_INT_FLAG_TPS: transmit process stopped status flag
1277       \arg        ENET_DMA_INT_FLAG_TBU: transmit buffer unavailable status flag
1278       \arg        ENET_DMA_INT_FLAG_TJT: transmit jabber timeout status flag
1279       \arg        ENET_DMA_INT_FLAG_RO: receive overflow status flag
1280       \arg        ENET_DMA_INT_FLAG_TU: transmit underflow status flag
1281       \arg        ENET_DMA_INT_FLAG_RS: receive status flag
1282       \arg        ENET_DMA_INT_FLAG_RBU: receive buffer unavailable status flag
1283       \arg        ENET_DMA_INT_FLAG_RPS: receive process stopped status flag
1284       \arg        ENET_DMA_INT_FLAG_RWT: receive watchdog timeout status flag
1285       \arg        ENET_DMA_INT_FLAG_ET: early transmit status flag
1286       \arg        ENET_DMA_INT_FLAG_FBE: fatal bus error status flag
1287       \arg        ENET_DMA_INT_FLAG_ER: early receive status flag
1288       \arg        ENET_DMA_INT_FLAG_AI: abnormal interrupt summary flag
1289       \arg        ENET_DMA_INT_FLAG_NI: normal interrupt summary flag
1290       \arg        ENET_DMA_INT_FLAG_MSC: MSC status flag
1291       \arg        ENET_DMA_INT_FLAG_WUM: WUM status flag
1292       \arg        ENET_DMA_INT_FLAG_TST: timestamp trigger status flag
1293     \param[out] none
1294     \retval     FlagStatus: SET or RESET
1295 */
enet_interrupt_flag_get(enet_int_flag_enum int_flag)1296 FlagStatus enet_interrupt_flag_get(enet_int_flag_enum int_flag)
1297 {
1298     if(RESET != (ENET_REG_VAL(int_flag) & BIT(ENET_BIT_POS(int_flag)))) {
1299         return SET;
1300     } else {
1301         return RESET;
1302     }
1303 }
1304 
1305 /*!
1306     \brief    clear ENET DMA interrupt flag
1307     \param[in]  int_flag_clear: clear ENET interrupt flag, refer to enet_int_flag_clear_enum
1308                 only one parameter can be selected which is shown as below
1309       \arg        ENET_DMA_INT_FLAG_TS_CLR: transmit status flag
1310       \arg        ENET_DMA_INT_FLAG_TPS_CLR: transmit process stopped status flag
1311       \arg        ENET_DMA_INT_FLAG_TBU_CLR: transmit buffer unavailable status flag
1312       \arg        ENET_DMA_INT_FLAG_TJT_CLR: transmit jabber timeout status flag
1313       \arg        ENET_DMA_INT_FLAG_RO_CLR: receive overflow status flag
1314       \arg        ENET_DMA_INT_FLAG_TU_CLR: transmit underflow status flag
1315       \arg        ENET_DMA_INT_FLAG_RS_CLR: receive status flag
1316       \arg        ENET_DMA_INT_FLAG_RBU_CLR: receive buffer unavailable status flag
1317       \arg        ENET_DMA_INT_FLAG_RPS_CLR: receive process stopped status flag
1318       \arg        ENET_DMA_INT_FLAG_RWT_CLR: receive watchdog timeout status flag
1319       \arg        ENET_DMA_INT_FLAG_ET_CLR: early transmit status flag
1320       \arg        ENET_DMA_INT_FLAG_FBE_CLR: fatal bus error status flag
1321       \arg        ENET_DMA_INT_FLAG_ER_CLR: early receive status flag
1322       \arg        ENET_DMA_INT_FLAG_AI_CLR: abnormal interrupt summary flag
1323       \arg        ENET_DMA_INT_FLAG_NI_CLR: normal interrupt summary flag
1324     \param[out] none
1325     \retval     none
1326 */
enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear)1327 void enet_interrupt_flag_clear(enet_int_flag_clear_enum int_flag_clear)
1328 {
1329     /* write 1 to the corresponding bit in ENET_DMA_STAT, to clear it */
1330     ENET_REG_VAL(int_flag_clear) = BIT(ENET_BIT_POS(int_flag_clear));
1331 }
1332 
1333 /*!
1334     \brief    ENET Tx function enable (include MAC and DMA module)
1335     \param[in]  none
1336     \param[out] none
1337     \retval     none
1338 */
enet_tx_enable(void)1339 void enet_tx_enable(void)
1340 {
1341     ENET_MAC_CFG |= ENET_MAC_CFG_TEN;
1342     enet_txfifo_flush();
1343     ENET_DMA_CTL |= ENET_DMA_CTL_STE;
1344 }
1345 
1346 /*!
1347     \brief    ENET Tx function disable (include MAC and DMA module)
1348     \param[in]  none
1349     \param[out] none
1350     \retval     none
1351 */
enet_tx_disable(void)1352 void enet_tx_disable(void)
1353 {
1354     ENET_DMA_CTL &= ~ENET_DMA_CTL_STE;
1355     enet_txfifo_flush();
1356     ENET_MAC_CFG &= ~ENET_MAC_CFG_TEN;
1357 }
1358 
1359 /*!
1360     \brief    ENET Rx function enable (include MAC and DMA module)
1361     \param[in]  none
1362     \param[out] none
1363     \retval     none
1364 */
enet_rx_enable(void)1365 void enet_rx_enable(void)
1366 {
1367     ENET_MAC_CFG |= ENET_MAC_CFG_REN;
1368     ENET_DMA_CTL |= ENET_DMA_CTL_SRE;
1369 }
1370 
1371 /*!
1372     \brief    ENET Rx function disable (include MAC and DMA module)
1373     \param[in]  none
1374     \param[out] none
1375     \retval     none
1376 */
enet_rx_disable(void)1377 void enet_rx_disable(void)
1378 {
1379     ENET_DMA_CTL &= ~ENET_DMA_CTL_SRE;
1380     ENET_MAC_CFG &= ~ENET_MAC_CFG_REN;
1381 }
1382 
1383 /*!
1384     \brief    put registers value into the application buffer
1385     \param[in]  type: register type which will be get, refer to enet_registers_type_enum,
1386                 only one parameter can be selected which is shown as below
1387       \arg        ALL_MAC_REG: get the registers within the offset scope between ENET_MAC_CFG and ENET_MAC_FCTH
1388       \arg        ALL_MSC_REG: get the registers within the offset scope between ENET_MSC_CTL and ENET_MSC_RGUFCNT
1389       \arg        ALL_PTP_REG: get the registers within the offset scope between ENET_PTP_TSCTL and ENET_PTP_PPSCTL
1390       \arg        ALL_DMA_REG: get the registers within the offset scope between ENET_DMA_BCTL and ENET_DMA_CRBADDR
1391     \param[in]  num: the number of registers that the user want to get
1392     \param[out] preg: the application buffer pointer for storing the register value
1393     \retval     none
1394 */
enet_registers_get(enet_registers_type_enum type,uint32_t * preg,uint32_t num)1395 void enet_registers_get(enet_registers_type_enum type, uint32_t *preg, uint32_t num)
1396 {
1397     uint32_t offset = 0U, max = 0U, limit = 0U;
1398 
1399     offset = (uint32_t)type;
1400     max = (uint32_t)type + num;
1401     limit = sizeof(enet_reg_tab) / sizeof(uint16_t);
1402 
1403     /* prevent element in this array is out of range */
1404     if(max > limit) {
1405         max = limit;
1406     }
1407 
1408     for(; offset < max; offset++) {
1409         /* get value of the corresponding register */
1410         *preg = REG32((ENET) + enet_reg_tab[offset]);
1411         preg++;
1412     }
1413 }
1414 
1415 /*!
1416     \brief    get the enet debug status from the debug register
1417     \param[in]  mac_debug: enet debug status
1418                 only one parameter can be selected which is shown as below
1419       \arg        ENET_MAC_RECEIVER_NOT_IDLE: MAC receiver is not in idle state
1420       \arg        ENET_RX_ASYNCHRONOUS_FIFO_STATE: Rx asynchronous FIFO status
1421       \arg        ENET_RXFIFO_WRITING: RxFIFO is doing write operation
1422       \arg        ENET_RXFIFO_READ_STATUS: RxFIFO read operation status
1423       \arg        ENET_RXFIFO_STATE: RxFIFO state
1424       \arg        ENET_MAC_TRANSMITTER_NOT_IDLE: MAC transmitter is not in idle state
1425       \arg        ENET_MAC_TRANSMITTER_STATUS: status of MAC transmitter
1426       \arg        ENET_PAUSE_CONDITION_STATUS: pause condition status
1427       \arg        ENET_TXFIFO_READ_STATUS: TxFIFO read operation status
1428       \arg        ENET_TXFIFO_WRITING: TxFIFO is doing write operation
1429       \arg        ENET_TXFIFO_NOT_EMPTY: TxFIFO is not empty
1430       \arg        ENET_TXFIFO_FULL: TxFIFO is full
1431     \param[out] none
1432     \retval     value of the status users want to get
1433 */
enet_debug_status_get(uint32_t mac_debug)1434 uint32_t enet_debug_status_get(uint32_t mac_debug)
1435 {
1436     uint32_t temp_state = 0U;
1437 
1438     switch(mac_debug) {
1439     case ENET_RX_ASYNCHRONOUS_FIFO_STATE:
1440         temp_state = GET_MAC_DBG_RXAFS(ENET_MAC_DBG);
1441         break;
1442     case ENET_RXFIFO_READ_STATUS:
1443         temp_state = GET_MAC_DBG_RXFRS(ENET_MAC_DBG);
1444         break;
1445     case ENET_RXFIFO_STATE:
1446         temp_state = GET_MAC_DBG_RXFS(ENET_MAC_DBG);
1447         break;
1448     case ENET_MAC_TRANSMITTER_STATUS:
1449         temp_state = GET_MAC_DBG_SOMT(ENET_MAC_DBG);
1450         break;
1451     case ENET_TXFIFO_READ_STATUS:
1452         temp_state = GET_MAC_DBG_TXFRS(ENET_MAC_DBG);
1453         break;
1454     default:
1455         if(RESET != (ENET_MAC_DBG & mac_debug)) {
1456             temp_state = 0x1U;
1457         }
1458         break;
1459     }
1460     return temp_state;
1461 }
1462 
1463 /*!
1464     \brief    enable the MAC address filter
1465     \param[in]  mac_addr: select which MAC address will be enable, refer to enet_macaddress_enum
1466       \arg        ENET_MAC_ADDRESS1: enable MAC address 1 filter
1467       \arg        ENET_MAC_ADDRESS2: enable MAC address 2 filter
1468       \arg        ENET_MAC_ADDRESS3: enable MAC address 3 filter
1469     \param[out] none
1470     \retval     none
1471 */
enet_address_filter_enable(enet_macaddress_enum mac_addr)1472 void enet_address_filter_enable(enet_macaddress_enum mac_addr)
1473 {
1474     REG32(ENET_ADDRH_BASE + mac_addr) |= ENET_MAC_ADDR1H_AFE;
1475 }
1476 
1477 /*!
1478     \brief    disable the MAC address filter
1479     \param[in]  mac_addr: select which MAC address will be disable, refer to enet_macaddress_enum
1480                 only one parameter can be selected which is shown as below
1481       \arg        ENET_MAC_ADDRESS1: disable MAC address 1 filter
1482       \arg        ENET_MAC_ADDRESS2: disable MAC address 2 filter
1483       \arg        ENET_MAC_ADDRESS3: disable MAC address 3 filter
1484     \param[out] none
1485     \retval     none
1486 */
enet_address_filter_disable(enet_macaddress_enum mac_addr)1487 void enet_address_filter_disable(enet_macaddress_enum mac_addr)
1488 {
1489     REG32(ENET_ADDRH_BASE + mac_addr) &= ~ENET_MAC_ADDR1H_AFE;
1490 }
1491 
1492 /*!
1493     \brief    configure the MAC address filter
1494     \param[in]  mac_addr: select which MAC address will be configured, refer to enet_macaddress_enum
1495                 only one parameter can be selected which is shown as below
1496       \arg        ENET_MAC_ADDRESS1: configure MAC address 1 filter
1497       \arg        ENET_MAC_ADDRESS2: configure MAC address 2 filter
1498       \arg        ENET_MAC_ADDRESS3: configure MAC address 3 filter
1499     \param[in]  addr_mask: select which MAC address bytes will be mask
1500                 one or more parameters can be selected which are shown as below
1501       \arg        ENET_ADDRESS_MASK_BYTE0: mask ENET_MAC_ADDR1L[7:0] bits
1502       \arg        ENET_ADDRESS_MASK_BYTE1: mask ENET_MAC_ADDR1L[15:8] bits
1503       \arg        ENET_ADDRESS_MASK_BYTE2: mask ENET_MAC_ADDR1L[23:16] bits
1504       \arg        ENET_ADDRESS_MASK_BYTE3: mask ENET_MAC_ADDR1L [31:24] bits
1505       \arg        ENET_ADDRESS_MASK_BYTE4: mask ENET_MAC_ADDR1H [7:0] bits
1506       \arg        ENET_ADDRESS_MASK_BYTE5: mask ENET_MAC_ADDR1H [15:8] bits
1507     \param[in]  filter_type: select which MAC address filter type will be selected
1508                 only one parameter can be selected which is shown as below
1509       \arg        ENET_ADDRESS_FILTER_SA: The MAC address is used to compared with the SA field of the received frame
1510       \arg        ENET_ADDRESS_FILTER_DA: The MAC address is used to compared with the DA field of the received frame
1511     \param[out] none
1512     \retval     none
1513 */
enet_address_filter_config(enet_macaddress_enum mac_addr,uint32_t addr_mask,uint32_t filter_type)1514 void enet_address_filter_config(enet_macaddress_enum mac_addr, uint32_t addr_mask, uint32_t filter_type)
1515 {
1516     uint32_t reg;
1517 
1518     /* get the address filter register value which is to be configured */
1519     reg = REG32(ENET_ADDRH_BASE + mac_addr);
1520 
1521     /* clear and configure the address filter register */
1522     reg &= ~(ENET_MAC_ADDR1H_MB | ENET_MAC_ADDR1H_SAF);
1523     reg |= (addr_mask | filter_type);
1524     REG32(ENET_ADDRH_BASE + mac_addr) = reg;
1525 }
1526 
1527 /*!
1528     \brief    PHY interface configuration (configure SMI clock and reset PHY chip)
1529     \param[in]  none
1530     \param[out] none
1531     \retval     ErrStatus: SUCCESS or ERROR
1532 */
enet_phy_config(void)1533 ErrStatus enet_phy_config(void)
1534 {
1535     uint32_t ahbclk;
1536     uint32_t reg;
1537     uint16_t phy_value;
1538     ErrStatus enet_state = ERROR;
1539 
1540     /* clear the previous MDC clock */
1541     reg = ENET_MAC_PHY_CTL;
1542     reg &= ~ENET_MAC_PHY_CTL_CLR;
1543 
1544     /* get the HCLK frequency */
1545     ahbclk = rcu_clock_freq_get(CK_AHB);
1546 
1547     /* configure MDC clock according to HCLK frequency range */
1548     if(ENET_RANGE(ahbclk, 20000000U, 35000000U)) {
1549         reg |= ENET_MDC_HCLK_DIV16;
1550     } else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)) {
1551         reg |= ENET_MDC_HCLK_DIV26;
1552     } else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)) {
1553         reg |= ENET_MDC_HCLK_DIV42;
1554     } else if(ENET_RANGE(ahbclk, 100000000U, 150000000U)) {
1555         reg |= ENET_MDC_HCLK_DIV62;
1556     } else if((ENET_RANGE(ahbclk, 150000000U, 240000000U)) || (240000000U == ahbclk)) {
1557         reg |= ENET_MDC_HCLK_DIV102;
1558     } else {
1559         return enet_state;
1560     }
1561     ENET_MAC_PHY_CTL = reg;
1562 
1563     /* reset PHY */
1564     phy_value = PHY_RESET;
1565     if(ERROR == (enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &phy_value))) {
1566         return enet_state;
1567     }
1568     /* PHY reset need some time */
1569     _ENET_DELAY_(ENET_DELAY_TO);
1570 
1571     /* check whether PHY reset is complete */
1572     if(ERROR == (enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &phy_value))) {
1573         return enet_state;
1574     }
1575 
1576     /* PHY reset complete */
1577     if(RESET == (phy_value & PHY_RESET)) {
1578         enet_state = SUCCESS;
1579     }
1580 
1581     return enet_state;
1582 }
1583 
1584 /*!
1585     \brief    write to / read from a PHY register
1586     \param[in]  direction: only one parameter can be selected which is shown as below, refer to enet_phydirection_enum
1587       \arg        ENET_PHY_WRITE: write data to phy register
1588       \arg        ENET_PHY_READ:  read data from phy register
1589     \param[in]  phy_address: 0x0000 - 0x001F
1590     \param[in]  phy_reg: 0x0000 - 0x001F
1591     \param[in]  pvalue: the value will be written to the PHY register in ENET_PHY_WRITE direction
1592     \param[out] pvalue: the value will be read from the PHY register in ENET_PHY_READ direction
1593     \retval     ErrStatus: SUCCESS or ERROR
1594 */
enet_phy_write_read(enet_phydirection_enum direction,uint16_t phy_address,uint16_t phy_reg,uint16_t * pvalue)1595 ErrStatus enet_phy_write_read(enet_phydirection_enum direction, uint16_t phy_address, uint16_t phy_reg, uint16_t *pvalue)
1596 {
1597     uint32_t reg, phy_flag;
1598     uint32_t timeout = 0U;
1599     ErrStatus enet_state = ERROR;
1600 
1601     /* configure ENET_MAC_PHY_CTL with write/read operation */
1602     reg = ENET_MAC_PHY_CTL;
1603     reg &= ~(ENET_MAC_PHY_CTL_PB | ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PR | ENET_MAC_PHY_CTL_PA);
1604     reg |= (direction | MAC_PHY_CTL_PR(phy_reg) | MAC_PHY_CTL_PA(phy_address) | ENET_MAC_PHY_CTL_PB);
1605 
1606     /* if do the write operation, write value to the register */
1607     if(ENET_PHY_WRITE == direction) {
1608         ENET_MAC_PHY_DATA = *pvalue;
1609     }
1610 
1611     /* do PHY write/read operation, and wait the operation complete  */
1612     ENET_MAC_PHY_CTL = reg;
1613     do {
1614         phy_flag = (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB);
1615         timeout++;
1616     } while((RESET != phy_flag) && (ENET_DELAY_TO != timeout));
1617 
1618     /* write/read operation complete */
1619     if(RESET == (ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)) {
1620         enet_state = SUCCESS;
1621     }
1622 
1623     /* if do the read operation, get value from the register */
1624     if(ENET_PHY_READ == direction) {
1625         *pvalue = (uint16_t)ENET_MAC_PHY_DATA;
1626     }
1627 
1628     return enet_state;
1629 }
1630 
1631 /*!
1632     \brief    enable the loopback function of PHY chip
1633     \param[in]  none
1634     \param[out] none
1635     \retval     ErrStatus: ERROR or SUCCESS
1636 */
enet_phyloopback_enable(void)1637 ErrStatus enet_phyloopback_enable(void)
1638 {
1639     uint16_t temp_phy = 0U;
1640     ErrStatus phy_state = ERROR;
1641 
1642     /* get the PHY configuration to update it */
1643     enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
1644 
1645     /* enable the PHY loopback mode */
1646     temp_phy |= PHY_LOOPBACK;
1647 
1648     /* update the PHY control register with the new configuration */
1649     phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
1650 
1651     return phy_state;
1652 }
1653 
1654 /*!
1655     \brief    disable the loopback function of PHY chip
1656     \param[in]  none
1657     \param[out] none
1658     \retval     ErrStatus: ERROR or SUCCESS
1659 */
enet_phyloopback_disable(void)1660 ErrStatus enet_phyloopback_disable(void)
1661 {
1662     uint16_t temp_phy = 0U;
1663     ErrStatus phy_state = ERROR;
1664 
1665     /* get the PHY configuration to update it */
1666     enet_phy_write_read(ENET_PHY_READ, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
1667 
1668     /* disable the PHY loopback mode */
1669     temp_phy &= (uint16_t)~PHY_LOOPBACK;
1670 
1671     /* update the PHY control register with the new configuration */
1672     phy_state = enet_phy_write_read(ENET_PHY_WRITE, PHY_ADDRESS, PHY_REG_BCR, &temp_phy);
1673 
1674     return phy_state;
1675 }
1676 
1677 /*!
1678     \brief    enable ENET forward feature
1679     \param[in]  feature: the feature of ENET forward mode
1680                 one or more parameters can be selected which are shown as below
1681       \arg        ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames
1682       \arg        ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding
1683       \arg        ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory
1684       \arg        ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames
1685     \param[out] none
1686     \retval     none
1687 */
enet_forward_feature_enable(uint32_t feature)1688 void enet_forward_feature_enable(uint32_t feature)
1689 {
1690     uint32_t mask;
1691 
1692     mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES)));
1693     ENET_MAC_CFG |= mask;
1694 
1695     mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP)));
1696     ENET_DMA_CTL |= (mask >> 2);
1697 }
1698 
1699 /*!
1700     \brief    disable ENET forward feature
1701     \param[in]  feature: the feature of ENET forward mode
1702                 one or more parameters can be selected which are shown as below
1703       \arg        ENET_AUTO_PADCRC_DROP: the function of the MAC strips the Pad/FCS field on received frames
1704       \arg        ENET_TYPEFRAME_CRC_DROP: the function that FCS field(last 4 bytes) of frame will be dropped before forwarding
1705       \arg        ENET_FORWARD_ERRFRAMES: the function that all frame received with error except runt error are forwarded to memory
1706       \arg        ENET_FORWARD_UNDERSZ_GOODFRAMES: the function that forwarding undersized good frames
1707     \param[out] none
1708     \retval     none
1709 */
enet_forward_feature_disable(uint32_t feature)1710 void enet_forward_feature_disable(uint32_t feature)
1711 {
1712     uint32_t mask;
1713 
1714     mask = (feature & (~(ENET_FORWARD_ERRFRAMES | ENET_FORWARD_UNDERSZ_GOODFRAMES)));
1715     ENET_MAC_CFG &= ~mask;
1716 
1717     mask = (feature & (~(ENET_AUTO_PADCRC_DROP | ENET_TYPEFRAME_CRC_DROP)));
1718     ENET_DMA_CTL &= ~(mask >> 2);
1719 }
1720 
1721 /*!
1722     \brief      enable ENET fliter feature
1723     \param[in]  feature: the feature of ENET fliter mode
1724                 one or more parameters can be selected which are shown as below
1725       \arg        ENET_SRC_FILTER: filter source address function
1726       \arg        ENET_SRC_FILTER_INVERSE: inverse source address filtering result function
1727       \arg        ENET_DEST_FILTER_INVERSE: inverse DA filtering result function
1728       \arg        ENET_MULTICAST_FILTER_PASS: pass all multicast frames function
1729       \arg        ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function
1730       \arg        ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function
1731       \arg        ENET_FILTER_MODE_EITHER: HASH or perfect filter function
1732     \param[out] none
1733     \retval     none
1734 */
enet_fliter_feature_enable(uint32_t feature)1735 void enet_fliter_feature_enable(uint32_t feature)
1736 {
1737     ENET_MAC_FRMF |= feature;
1738 }
1739 
1740 /*!
1741     \brief    disable ENET fliter feature
1742     \param[in]  feature: the feature of ENET fliter mode
1743                 one or more parameters can be selected which are shown as below
1744       \arg        ENET_SRC_FILTER: filter source address function
1745       \arg        ENET_SRC_FILTER_INVERSE: inverse source address filtering result function
1746       \arg        ENET_DEST_FILTER_INVERSE: inverse DA filtering result function
1747       \arg        ENET_MULTICAST_FILTER_PASS: pass all multicast frames function
1748       \arg        ENET_MULTICAST_FILTER_HASH_MODE: HASH multicast filter function
1749       \arg        ENET_UNICAST_FILTER_HASH_MODE: HASH unicast filter function
1750       \arg        ENET_FILTER_MODE_EITHER: HASH or perfect filter function
1751     \param[out] none
1752     \retval     none
1753 */
enet_fliter_feature_disable(uint32_t feature)1754 void enet_fliter_feature_disable(uint32_t feature)
1755 {
1756     ENET_MAC_FRMF &= ~feature;
1757 }
1758 
1759 /*!
1760     \brief    generate the pause frame, ENET will send pause frame after enable transmit flow control
1761                 this function only use in full-dulex mode
1762     \param[in]  none
1763     \param[out] none
1764     \retval     ErrStatus: ERROR or SUCCESS
1765 */
enet_pauseframe_generate(void)1766 ErrStatus enet_pauseframe_generate(void)
1767 {
1768     ErrStatus enet_state = ERROR;
1769     uint32_t temp = 0U;
1770 
1771     /* in full-duplex mode, must make sure this bit is 0 before writing register */
1772     temp = ENET_MAC_FCTL & ENET_MAC_FCTL_FLCBBKPA;
1773     if(RESET == temp) {
1774         ENET_MAC_FCTL |= ENET_MAC_FCTL_FLCBBKPA;
1775         enet_state = SUCCESS;
1776     }
1777     return enet_state;
1778 }
1779 
1780 /*!
1781     \brief    configure the pause frame detect type
1782     \param[in]  detect: pause frame detect type
1783                 only one parameter can be selected which is shown as below
1784       \arg        ENET_MAC0_AND_UNIQUE_ADDRESS_PAUSEDETECT: besides the unique multicast address, MAC can also
1785                                                             use the MAC0 address to detecting pause frame
1786       \arg        ENET_UNIQUE_PAUSEDETECT: only the unique multicast address for pause frame which is specified
1787                                            in IEEE802.3 can be detected
1788     \param[out] none
1789     \retval     none
1790 */
enet_pauseframe_detect_config(uint32_t detect)1791 void enet_pauseframe_detect_config(uint32_t detect)
1792 {
1793     ENET_MAC_FCTL &= ~ENET_MAC_FCTL_UPFDT;
1794     ENET_MAC_FCTL |= detect;
1795 }
1796 
1797 /*!
1798     \brief    configure the pause frame parameters
1799     \param[in]  pausetime: pause time in transmit pause control frame
1800     \param[in]  pause_threshold: the threshold of the pause timer for retransmitting frames automatically
1801                 this value must make sure to be less than configured pause time
1802                 only one parameter can be selected which is shown as below
1803       \arg        ENET_PAUSETIME_MINUS4: pause time minus 4 slot times
1804       \arg        ENET_PAUSETIME_MINUS28: pause time minus 28 slot times
1805       \arg        ENET_PAUSETIME_MINUS144: pause time minus 144 slot times
1806       \arg        ENET_PAUSETIME_MINUS256: pause time minus 256 slot times
1807     \param[out] none
1808     \retval     none
1809 */
enet_pauseframe_config(uint32_t pausetime,uint32_t pause_threshold)1810 void enet_pauseframe_config(uint32_t pausetime, uint32_t pause_threshold)
1811 {
1812     ENET_MAC_FCTL &= ~(ENET_MAC_FCTL_PTM | ENET_MAC_FCTL_PLTS);
1813     ENET_MAC_FCTL |= (MAC_FCTL_PTM(pausetime) | pause_threshold);
1814 }
1815 
1816 /*!
1817     \brief    configure the threshold of the flow control(deactive and active threshold)
1818     \param[in]  deactive: the threshold of the deactive flow control
1819                 this value should always be less than active flow control value
1820                 only one parameter can be selected which is shown as below
1821       \arg        ENET_DEACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes
1822       \arg        ENET_DEACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes
1823       \arg        ENET_DEACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes
1824       \arg        ENET_DEACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes
1825       \arg        ENET_DEACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes
1826       \arg        ENET_DEACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes
1827       \arg        ENET_DEACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes
1828     \param[in]  active: the threshold of the active flow control
1829                 only one parameter can be selected which is shown as below
1830       \arg        ENET_ACTIVE_THRESHOLD_256BYTES: threshold level is 256 bytes
1831       \arg        ENET_ACTIVE_THRESHOLD_512BYTES: threshold level is 512 bytes
1832       \arg        ENET_ACTIVE_THRESHOLD_768BYTES: threshold level is 768 bytes
1833       \arg        ENET_ACTIVE_THRESHOLD_1024BYTES: threshold level is 1024 bytes
1834       \arg        ENET_ACTIVE_THRESHOLD_1280BYTES: threshold level is 1280 bytes
1835       \arg        ENET_ACTIVE_THRESHOLD_1536BYTES: threshold level is 1536 bytes
1836       \arg        ENET_ACTIVE_THRESHOLD_1792BYTES: threshold level is 1792 bytes
1837     \param[out] none
1838     \retval     none
1839 */
enet_flowcontrol_threshold_config(uint32_t deactive,uint32_t active)1840 void enet_flowcontrol_threshold_config(uint32_t deactive, uint32_t active)
1841 {
1842     ENET_MAC_FCTH = ((deactive | active) >> 8);
1843 }
1844 
1845 /*!
1846     \brief    enable ENET flow control feature
1847     \param[in]  feature: the feature of ENET flow control mode
1848                 one or more parameters can be selected which are shown as below
1849       \arg        ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function
1850       \arg        ENET_TX_FLOWCONTROL: the flow control operation in the MAC
1851       \arg        ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it
1852       \arg        ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode)
1853     \param[out] none
1854     \retval     none
1855 */
enet_flowcontrol_feature_enable(uint32_t feature)1856 void enet_flowcontrol_feature_enable(uint32_t feature)
1857 {
1858     if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)) {
1859         ENET_MAC_FCTL &= ~ENET_ZERO_QUANTA_PAUSE;
1860     }
1861     feature &= ~ENET_ZERO_QUANTA_PAUSE;
1862     ENET_MAC_FCTL |= feature;
1863 }
1864 
1865 /*!
1866     \brief    disable ENET flow control feature
1867     \param[in]  feature: the feature of ENET flow control mode
1868                 one or more parameters can be selected which are shown as below
1869       \arg        ENET_ZERO_QUANTA_PAUSE: the automatic zero-quanta generation function
1870       \arg        ENET_TX_FLOWCONTROL: the flow control operation in the MAC
1871       \arg        ENET_RX_FLOWCONTROL: decoding function for the received pause frame and process it
1872       \arg        ENET_BACK_PRESSURE: back pressure operation in the MAC(only use in half-dulex mode)
1873     \param[out] none
1874     \retval     none
1875 */
enet_flowcontrol_feature_disable(uint32_t feature)1876 void enet_flowcontrol_feature_disable(uint32_t feature)
1877 {
1878     if(RESET != (feature & ENET_ZERO_QUANTA_PAUSE)) {
1879         ENET_MAC_FCTL |= ENET_ZERO_QUANTA_PAUSE;
1880     }
1881     feature &= ~ENET_ZERO_QUANTA_PAUSE;
1882     ENET_MAC_FCTL &= ~feature;
1883 }
1884 
1885 /*!
1886     \brief    get the dma transmit/receive process state
1887     \param[in]  direction: choose the direction of dma process which users want to check, refer to enet_dmadirection_enum
1888                 only one parameter can be selected which is shown as below
1889       \arg        ENET_DMA_TX: dma transmit process
1890       \arg        ENET_DMA_RX: dma receive process
1891     \param[out] none
1892     \retval     state of dma process, the value range shows below:
1893                   ENET_RX_STATE_STOPPED, ENET_RX_STATE_FETCHING, ENET_RX_STATE_WAITING,
1894                   ENET_RX_STATE_SUSPENDED, ENET_RX_STATE_CLOSING, ENET_RX_STATE_QUEUING,
1895                   ENET_TX_STATE_STOPPED, ENET_TX_STATE_FETCHING, ENET_TX_STATE_WAITING,
1896                   ENET_TX_STATE_READING, ENET_TX_STATE_SUSPENDED, ENET_TX_STATE_CLOSING
1897 */
enet_dmaprocess_state_get(enet_dmadirection_enum direction)1898 uint32_t enet_dmaprocess_state_get(enet_dmadirection_enum direction)
1899 {
1900     uint32_t reval;
1901     reval = (uint32_t)(ENET_DMA_STAT & (uint32_t)direction);
1902     return reval;
1903 }
1904 
1905 /*!
1906     \brief    poll the DMA transmission/reception enable by writing any value to the
1907                 ENET_DMA_TPEN/ENET_DMA_RPEN register, this will make the DMA to resume transmission/reception
1908     \param[in]  direction: choose the direction of DMA process which users want to resume, refer to enet_dmadirection_enum
1909                 only one parameter can be selected which is shown as below
1910       \arg        ENET_DMA_TX: DMA transmit process
1911       \arg        ENET_DMA_RX: DMA receive process
1912     \param[out] none
1913     \retval     none
1914 */
enet_dmaprocess_resume(enet_dmadirection_enum direction)1915 void enet_dmaprocess_resume(enet_dmadirection_enum direction)
1916 {
1917     if(ENET_DMA_TX == direction) {
1918         ENET_DMA_TPEN = 0U;
1919     } else {
1920         ENET_DMA_RPEN = 0U;
1921     }
1922 }
1923 
1924 /*!
1925     \brief    check and recover the Rx process
1926     \param[in]  none
1927     \param[out] none
1928     \retval     none
1929 */
enet_rxprocess_check_recovery(void)1930 void enet_rxprocess_check_recovery(void)
1931 {
1932     uint32_t status;
1933 
1934     /* get DAV information of current RxDMA descriptor */
1935     status = dma_current_rxdesc->status;
1936     status &= ENET_RDES0_DAV;
1937 
1938     /* if current descriptor is owned by DMA, but the descriptor address mismatches with
1939     receive descriptor address pointer updated by RxDMA controller */
1940     if((ENET_DMA_CRDADDR != ((uint32_t)dma_current_rxdesc)) &&
1941             (ENET_RDES0_DAV == status)) {
1942         dma_current_rxdesc = (enet_descriptors_struct *)ENET_DMA_CRDADDR;
1943     }
1944 }
1945 
1946 /*!
1947     \brief    flush the ENET transmit FIFO, and wait until the flush operation completes
1948     \param[in]  none
1949     \param[out] none
1950     \retval     ErrStatus: ERROR or SUCCESS
1951 */
enet_txfifo_flush(void)1952 ErrStatus enet_txfifo_flush(void)
1953 {
1954     uint32_t flush_state;
1955     uint32_t timeout = 0U;
1956     ErrStatus enet_state = ERROR;
1957 
1958     /* set the FTF bit for flushing transmit FIFO */
1959     ENET_DMA_CTL |= ENET_DMA_CTL_FTF;
1960     /* wait until the flush operation completes */
1961     do {
1962         flush_state = ENET_DMA_CTL & ENET_DMA_CTL_FTF;
1963         timeout++;
1964     } while((RESET != flush_state) && (timeout < ENET_DELAY_TO));
1965     /* return ERROR due to timeout */
1966     if(RESET == flush_state) {
1967         enet_state = SUCCESS;
1968     }
1969 
1970     return  enet_state;
1971 }
1972 
1973 /*!
1974     \brief    get the transmit/receive address of current descriptor, or current buffer, or descriptor table
1975     \param[in]  addr_get: choose the address which users want to get, refer to enet_desc_reg_enum
1976                 only one parameter can be selected which is shown as below
1977       \arg        ENET_RX_DESC_TABLE: the start address of the receive descriptor table
1978       \arg        ENET_RX_CURRENT_DESC: the start descriptor address of the current receive descriptor read by
1979                                         the RxDMA controller
1980       \arg        ENET_RX_CURRENT_BUFFER: the current receive buffer address being read by the RxDMA controller
1981       \arg        ENET_TX_DESC_TABLE: the start address of the transmit descriptor table
1982       \arg        ENET_TX_CURRENT_DESC: the start descriptor address of the current transmit descriptor read by
1983                                         the TxDMA controller
1984       \arg        ENET_TX_CURRENT_BUFFER: the current transmit buffer address being read by the TxDMA controller
1985     \param[out] none
1986     \retval     address value
1987 */
enet_current_desc_address_get(enet_desc_reg_enum addr_get)1988 uint32_t enet_current_desc_address_get(enet_desc_reg_enum addr_get)
1989 {
1990     uint32_t reval = 0U;
1991 
1992     reval = REG32((ENET) + (uint32_t)addr_get);
1993     return reval;
1994 }
1995 
1996 /*!
1997     \brief    get the Tx or Rx descriptor information
1998     \param[in]  desc: the descriptor pointer which users want to get information
1999     \param[in]  info_get: the descriptor information type which is selected, refer to enet_descstate_enum
2000                 only one parameter can be selected which is shown as below
2001       \arg        RXDESC_BUFFER_1_SIZE: receive buffer 1 size
2002       \arg        RXDESC_BUFFER_2_SIZE: receive buffer 2 size
2003       \arg        RXDESC_FRAME_LENGTH: the byte length of the received frame that was transferred to the buffer
2004       \arg        TXDESC_COLLISION_COUNT: the number of collisions occurred before the frame was transmitted
2005       \arg        RXDESC_BUFFER_1_ADDR: the buffer1 address of the Rx frame
2006       \arg        TXDESC_BUFFER_1_ADDR: the buffer1 address of the Tx frame
2007     \param[out] none
2008     \retval     descriptor information, if value is 0xFFFFFFFFU, means the false input parameter
2009 */
enet_desc_information_get(enet_descriptors_struct * desc,enet_descstate_enum info_get)2010 uint32_t enet_desc_information_get(enet_descriptors_struct *desc, enet_descstate_enum info_get)
2011 {
2012     uint32_t reval = 0xFFFFFFFFU;
2013 
2014     switch(info_get) {
2015     case RXDESC_BUFFER_1_SIZE:
2016         reval = GET_RDES1_RB1S(desc->control_buffer_size);
2017         break;
2018     case RXDESC_BUFFER_2_SIZE:
2019         reval = GET_RDES1_RB2S(desc->control_buffer_size);
2020         break;
2021     case RXDESC_FRAME_LENGTH:
2022         reval = GET_RDES0_FRML(desc->status);
2023         if(reval > 4U) {
2024             reval = reval - 4U;
2025 
2026             /* if is a type frame, and CRC is not included in forwarding frame */
2027             if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (desc->status & ENET_RDES0_FRMT))) {
2028                 reval = reval + 4U;
2029             }
2030         } else {
2031             reval = 0U;
2032         }
2033 
2034         break;
2035     case RXDESC_BUFFER_1_ADDR:
2036         reval = desc->buffer1_addr;
2037         break;
2038     case TXDESC_BUFFER_1_ADDR:
2039         reval = desc->buffer1_addr;
2040         break;
2041     case TXDESC_COLLISION_COUNT:
2042         reval = GET_TDES0_COCNT(desc->status);
2043         break;
2044     default:
2045         break;
2046     }
2047     return reval;
2048 }
2049 
2050 /*!
2051     \brief    get the number of missed frames during receiving
2052     \param[in]  none
2053     \param[out] rxfifo_drop: pointer to the number of frames dropped by RxFIFO
2054     \param[out] rxdma_drop: pointer to the number of frames missed by the RxDMA controller
2055     \retval     none
2056 */
enet_missed_frame_counter_get(uint32_t * rxfifo_drop,uint32_t * rxdma_drop)2057 void enet_missed_frame_counter_get(uint32_t *rxfifo_drop, uint32_t *rxdma_drop)
2058 {
2059     uint32_t temp_counter = 0U;
2060 
2061     temp_counter = ENET_DMA_MFBOCNT;
2062     *rxfifo_drop = GET_DMA_MFBOCNT_MSFA(temp_counter);
2063     *rxdma_drop = GET_DMA_MFBOCNT_MSFC(temp_counter);
2064 }
2065 
2066 /*!
2067     \brief    get the bit flag of ENET DMA descriptor
2068     \param[in]  desc: the descriptor pointer which users want to get flag
2069     \param[in]  desc_flag: the bit flag of ENET DMA descriptor
2070                 only one parameter can be selected which is shown as below
2071       \arg        ENET_TDES0_DB: deferred
2072       \arg        ENET_TDES0_UFE: underflow error
2073       \arg        ENET_TDES0_EXD: excessive deferral
2074       \arg        ENET_TDES0_VFRM: VLAN frame
2075       \arg        ENET_TDES0_ECO: excessive collision
2076       \arg        ENET_TDES0_LCO: late collision
2077       \arg        ENET_TDES0_NCA: no carrier
2078       \arg        ENET_TDES0_LCA: loss of carrier
2079       \arg        ENET_TDES0_IPPE: IP payload error
2080       \arg        ENET_TDES0_FRMF: frame flushed
2081       \arg        ENET_TDES0_JT: jabber timeout
2082       \arg        ENET_TDES0_ES: error summary
2083       \arg        ENET_TDES0_IPHE: IP header error
2084       \arg        ENET_TDES0_TTMSS: transmit timestamp status
2085       \arg        ENET_TDES0_TCHM: the second address chained mode
2086       \arg        ENET_TDES0_TERM: transmit end of ring mode
2087       \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
2088       \arg        ENET_TDES0_DPAD: disable adding pad
2089       \arg        ENET_TDES0_DCRC: disable CRC
2090       \arg        ENET_TDES0_FSG: first segment
2091       \arg        ENET_TDES0_LSG: last segment
2092       \arg        ENET_TDES0_INTC: interrupt on completion
2093       \arg        ENET_TDES0_DAV: DAV bit
2094 
2095       \arg        ENET_RDES0_PCERR: payload checksum error
2096       \arg        ENET_RDES0_EXSV: extended status valid
2097       \arg        ENET_RDES0_CERR: CRC error
2098       \arg        ENET_RDES0_DBERR: dribble bit error
2099       \arg        ENET_RDES0_RERR: receive error
2100       \arg        ENET_RDES0_RWDT: receive watchdog timeout
2101       \arg        ENET_RDES0_FRMT: frame type
2102       \arg        ENET_RDES0_LCO: late collision
2103       \arg        ENET_RDES0_IPHERR: IP frame header error
2104       \arg        ENET_RDES0_TSV: timestamp valid
2105       \arg        ENET_RDES0_LDES: last descriptor
2106       \arg        ENET_RDES0_FDES: first descriptor
2107       \arg        ENET_RDES0_VTAG: VLAN tag
2108       \arg        ENET_RDES0_OERR: overflow error
2109       \arg        ENET_RDES0_LERR: length error
2110       \arg        ENET_RDES0_SAFF: SA filter fail
2111       \arg        ENET_RDES0_DERR: descriptor error
2112       \arg        ENET_RDES0_ERRS: error summary
2113       \arg        ENET_RDES0_DAFF: destination address filter fail
2114       \arg        ENET_RDES0_DAV: descriptor available
2115     \param[out] none
2116     \retval     FlagStatus: SET or RESET
2117 */
enet_desc_flag_get(enet_descriptors_struct * desc,uint32_t desc_flag)2118 FlagStatus enet_desc_flag_get(enet_descriptors_struct *desc, uint32_t desc_flag)
2119 {
2120     FlagStatus enet_flag = RESET;
2121 
2122     if((uint32_t)RESET != (desc->status & desc_flag)) {
2123         enet_flag = SET;
2124     }
2125 
2126     return enet_flag;
2127 }
2128 
2129 /*!
2130     \brief    set the bit flag of ENET DMA descriptor
2131     \param[in]  desc: the descriptor pointer which users want to set flag
2132     \param[in]  desc_flag: the bit flag of ENET DMA descriptor
2133                 only one parameter can be selected which is shown as below
2134       \arg        ENET_TDES0_VFRM: VLAN frame
2135       \arg        ENET_TDES0_FRMF: frame flushed
2136       \arg        ENET_TDES0_TCHM: the second address chained mode
2137       \arg        ENET_TDES0_TERM: transmit end of ring mode
2138       \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
2139       \arg        ENET_TDES0_DPAD: disable adding pad
2140       \arg        ENET_TDES0_DCRC: disable CRC
2141       \arg        ENET_TDES0_FSG: first segment
2142       \arg        ENET_TDES0_LSG: last segment
2143       \arg        ENET_TDES0_INTC: interrupt on completion
2144       \arg        ENET_TDES0_DAV: DAV bit
2145       \arg        ENET_RDES0_DAV: descriptor available
2146     \param[out] none
2147     \retval     none
2148 */
enet_desc_flag_set(enet_descriptors_struct * desc,uint32_t desc_flag)2149 void enet_desc_flag_set(enet_descriptors_struct *desc, uint32_t desc_flag)
2150 {
2151     desc->status |= desc_flag;
2152 }
2153 
2154 /*!
2155     \brief    clear the bit flag of ENET DMA descriptor
2156     \param[in]  desc: the descriptor pointer which users want to clear flag
2157     \param[in]  desc_flag: the bit flag of ENET DMA descriptor
2158                 only one parameter can be selected which is shown as below
2159       \arg        ENET_TDES0_VFRM: VLAN frame
2160       \arg        ENET_TDES0_FRMF: frame flushed
2161       \arg        ENET_TDES0_TCHM: the second address chained mode
2162       \arg        ENET_TDES0_TERM: transmit end of ring mode
2163       \arg        ENET_TDES0_TTSEN: transmit timestamp function enable
2164       \arg        ENET_TDES0_DPAD: disable adding pad
2165       \arg        ENET_TDES0_DCRC: disable CRC
2166       \arg        ENET_TDES0_FSG: first segment
2167       \arg        ENET_TDES0_LSG: last segment
2168       \arg        ENET_TDES0_INTC: interrupt on completion
2169       \arg        ENET_TDES0_DAV: DAV bit
2170       \arg        ENET_RDES0_DAV: descriptor available
2171     \param[out] none
2172     \retval     none
2173 */
enet_desc_flag_clear(enet_descriptors_struct * desc,uint32_t desc_flag)2174 void enet_desc_flag_clear(enet_descriptors_struct *desc, uint32_t desc_flag)
2175 {
2176     desc->status &= ~desc_flag;
2177 }
2178 
2179 /*!
2180     \brief    when receiving completed, set RS bit in ENET_DMA_STAT register will immediately set
2181     \param[in]  desc: the descriptor pointer which users want to configure
2182     \param[out] none
2183     \retval     none
2184 */
enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct * desc)2185 void enet_rx_desc_immediate_receive_complete_interrupt(enet_descriptors_struct *desc)
2186 {
2187     desc->control_buffer_size &= ~ENET_RDES1_DINTC;
2188 }
2189 
2190 /*!
2191     \brief    when receiving completed, set RS bit in ENET_DMA_STAT register will is set after a configurable delay time
2192     \param[in]  desc: the descriptor pointer which users want to configure
2193     \param[in]  delay_time: delay a time of 256*delay_time HCLK(0x00000000 - 0x000000FF)
2194     \param[out] none
2195     \retval     none
2196 */
enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct * desc,uint32_t delay_time)2197 void enet_rx_desc_delay_receive_complete_interrupt(enet_descriptors_struct *desc, uint32_t delay_time)
2198 {
2199     desc->control_buffer_size |= ENET_RDES1_DINTC;
2200     ENET_DMA_RSWDC = DMA_RSWDC_WDCFRS(delay_time);
2201 }
2202 
2203 /*!
2204     \brief    drop current receive frame
2205     \param[in]  none
2206     \param[out] none
2207     \retval     none
2208 */
enet_rxframe_drop(void)2209 void enet_rxframe_drop(void)
2210 {
2211     /* enable reception, descriptor is owned by DMA */
2212     dma_current_rxdesc->status = ENET_RDES0_DAV;
2213 
2214     /* chained mode */
2215     if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) {
2216         if(NULL != dma_current_ptp_rxdesc) {
2217             dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->buffer2_next_desc_addr);
2218             /* if it is the last ptp descriptor */
2219             if(0U != dma_current_ptp_rxdesc->status) {
2220                 /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
2221                 dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status);
2222             } else {
2223                 /* ponter to the next ptp descriptor */
2224                 dma_current_ptp_rxdesc++;
2225             }
2226         } else {
2227             dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_rxdesc->buffer2_next_desc_addr);
2228         }
2229 
2230     } else {
2231         /* ring mode */
2232         if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) {
2233             /* if is the last descriptor in table, the next descriptor is the table header */
2234             dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR);
2235             if(NULL != dma_current_ptp_rxdesc) {
2236                 dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status);
2237             }
2238         } else {
2239             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
2240             dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
2241             if(NULL != dma_current_ptp_rxdesc) {
2242                 dma_current_ptp_rxdesc++;
2243             }
2244         }
2245     }
2246 }
2247 
2248 /*!
2249     \brief    enable DMA feature
2250     \param[in]  feature: the feature of DMA mode
2251                 one or more parameters can be selected which are shown as below
2252       \arg        ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function
2253       \arg        ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function
2254     \param[out] none
2255     \retval     none
2256 */
enet_dma_feature_enable(uint32_t feature)2257 void enet_dma_feature_enable(uint32_t feature)
2258 {
2259     ENET_DMA_CTL |= feature;
2260 }
2261 
2262 /*!
2263     \brief    disable DMA feature
2264     \param[in]  feature: the feature of DMA mode
2265                 one or more parameters can be selected which are shown as below
2266       \arg        ENET_NO_FLUSH_RXFRAME: RxDMA does not flushes frames function
2267       \arg        ENET_SECONDFRAME_OPT: TxDMA controller operate on second frame function
2268     \param[out] none
2269     \retval     none
2270 */
enet_dma_feature_disable(uint32_t feature)2271 void enet_dma_feature_disable(uint32_t feature)
2272 {
2273     ENET_DMA_CTL &= ~feature;
2274 }
2275 
2276 #ifdef SELECT_DESCRIPTORS_ENHANCED_MODE
2277 /*!
2278     \brief    get the bit of extended status flag in ENET DMA descriptor
2279     \param[in]  desc: the descriptor pointer which users want to get the extended status flag
2280     \param[in]  desc_status: the extended status want to get
2281                 only one parameter can be selected which is shown as below
2282       \arg        ENET_RDES4_IPPLDT: IP frame payload type
2283       \arg        ENET_RDES4_IPHERR: IP frame header error
2284       \arg        ENET_RDES4_IPPLDERR: IP frame payload error
2285       \arg        ENET_RDES4_IPCKSB: IP frame checksum bypassed
2286       \arg        ENET_RDES4_IPF4: IP frame in version 4
2287       \arg        ENET_RDES4_IPF6: IP frame in version 6
2288       \arg        ENET_RDES4_PTPMT: PTP message type
2289       \arg        ENET_RDES4_PTPOEF: PTP on ethernet frame
2290       \arg        ENET_RDES4_PTPVF: PTP version format
2291     \param[out] none
2292     \retval     value of extended status
2293 */
enet_rx_desc_enhanced_status_get(enet_descriptors_struct * desc,uint32_t desc_status)2294 uint32_t enet_rx_desc_enhanced_status_get(enet_descriptors_struct *desc, uint32_t desc_status)
2295 {
2296     uint32_t reval = 0xFFFFFFFFU;
2297 
2298     switch(desc_status) {
2299     case ENET_RDES4_IPPLDT:
2300         reval = GET_RDES4_IPPLDT(desc->extended_status);
2301         break;
2302     case ENET_RDES4_PTPMT:
2303         reval = GET_RDES4_PTPMT(desc->extended_status);
2304         break;
2305     default:
2306         if((uint32_t)RESET != (desc->extended_status & desc_status)) {
2307             reval = 1U;
2308         } else {
2309             reval = 0U;
2310         }
2311     }
2312 
2313     return reval;
2314 }
2315 
2316 /*!
2317     \brief    configure descriptor to work in enhanced mode
2318     \param[in]  none
2319     \param[out] none
2320     \retval     none
2321 */
enet_desc_select_enhanced_mode(void)2322 void enet_desc_select_enhanced_mode(void)
2323 {
2324     ENET_DMA_BCTL |= ENET_DMA_BCTL_DFM;
2325 }
2326 
2327 /*!
2328     \brief    initialize the DMA Tx/Rx descriptors's parameters in enhanced chain mode with ptp function
2329     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
2330                 only one parameter can be selected which is shown as below
2331       \arg        ENET_DMA_TX: DMA Tx descriptors
2332       \arg        ENET_DMA_RX: DMA Rx descriptors
2333     \param[out] none
2334     \retval     none
2335 */
enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction)2336 void enet_ptp_enhanced_descriptors_chain_init(enet_dmadirection_enum direction)
2337 {
2338     uint32_t num = 0U, count = 0U, maxsize = 0U;
2339     uint32_t desc_status = 0U, desc_bufsize = 0U;
2340     enet_descriptors_struct *desc, *desc_tab;
2341     uint8_t *buf;
2342 
2343     /* if want to initialize DMA Tx descriptors */
2344     if(ENET_DMA_TX == direction) {
2345         /* save a copy of the DMA Tx descriptors */
2346         desc_tab = txdesc_tab;
2347         buf = &tx_buff[0][0];
2348         count = ENET_TXBUF_NUM;
2349         maxsize = ENET_TXBUF_SIZE;
2350 
2351         /* select chain mode, and enable transmit timestamp function */
2352         desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN;
2353 
2354         /* configure DMA Tx descriptor table address register */
2355         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
2356         dma_current_txdesc = desc_tab;
2357     } else {
2358         /* if want to initialize DMA Rx descriptors */
2359         /* save a copy of the DMA Rx descriptors */
2360         desc_tab = rxdesc_tab;
2361         buf = &rx_buff[0][0];
2362         count = ENET_RXBUF_NUM;
2363         maxsize = ENET_RXBUF_SIZE;
2364 
2365         /* enable receiving */
2366         desc_status = ENET_RDES0_DAV;
2367         /* select receive chained mode and set buffer1 size */
2368         desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE;
2369 
2370         /* configure DMA Rx descriptor table address register */
2371         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
2372         dma_current_rxdesc = desc_tab;
2373     }
2374 
2375     /* configuration each descriptor */
2376     for(num = 0U; num < count; num++) {
2377         /* get the pointer to the next descriptor of the descriptor table */
2378         desc = desc_tab + num;
2379 
2380         /* configure descriptors */
2381         desc->status = desc_status;
2382         desc->control_buffer_size = desc_bufsize;
2383         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
2384 
2385         /* if is not the last descriptor */
2386         if(num < (count - 1U)) {
2387             /* configure the next descriptor address */
2388             desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U);
2389         } else {
2390             /* when it is the last descriptor, the next descriptor address
2391             equals to first descriptor address in descriptor table */
2392             desc->buffer2_next_desc_addr = (uint32_t)desc_tab;
2393         }
2394     }
2395 }
2396 
2397 /*!
2398     \brief    initialize the DMA Tx/Rx descriptors's parameters in enhanced ring mode with ptp function
2399     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
2400                 only one parameter can be selected which is shown as below
2401       \arg        ENET_DMA_TX: DMA Tx descriptors
2402       \arg        ENET_DMA_RX: DMA Rx descriptors
2403     \param[out] none
2404     \retval     none
2405 */
enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction)2406 void enet_ptp_enhanced_descriptors_ring_init(enet_dmadirection_enum direction)
2407 {
2408     uint32_t num = 0U, count = 0U, maxsize = 0U;
2409     uint32_t desc_status = 0U, desc_bufsize = 0U;
2410     enet_descriptors_struct *desc;
2411     enet_descriptors_struct *desc_tab;
2412     uint8_t *buf;
2413 
2414     /* configure descriptor skip length */
2415     ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL;
2416     ENET_DMA_BCTL |= DMA_BCTL_DPSL(0);
2417 
2418     /* if want to initialize DMA Tx descriptors */
2419     if(ENET_DMA_TX == direction) {
2420         /* save a copy of the DMA Tx descriptors */
2421         desc_tab = txdesc_tab;
2422         buf = &tx_buff[0][0];
2423         count = ENET_TXBUF_NUM;
2424         maxsize = ENET_TXBUF_SIZE;
2425 
2426         /* select ring mode, and enable transmit timestamp function */
2427         desc_status = ENET_TDES0_TTSEN;
2428 
2429         /* configure DMA Tx descriptor table address register */
2430         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
2431         dma_current_txdesc = desc_tab;
2432     } else {
2433         /* if want to initialize DMA Rx descriptors */
2434         /* save a copy of the DMA Rx descriptors */
2435         desc_tab = rxdesc_tab;
2436         buf = &rx_buff[0][0];
2437         count = ENET_RXBUF_NUM;
2438         maxsize = ENET_RXBUF_SIZE;
2439 
2440         /* enable receiving */
2441         desc_status = ENET_RDES0_DAV;
2442         /* set buffer1 size */
2443         desc_bufsize = ENET_RXBUF_SIZE;
2444 
2445         /* configure DMA Rx descriptor table address register */
2446         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
2447         dma_current_rxdesc = desc_tab;
2448     }
2449 
2450     /* configure each descriptor */
2451     for(num = 0U; num < count; num++) {
2452         /* get the pointer to the next descriptor of the descriptor table */
2453         desc = desc_tab + num;
2454 
2455         /* configure descriptors */
2456         desc->status = desc_status;
2457         desc->control_buffer_size = desc_bufsize;
2458         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
2459 
2460         /* when it is the last descriptor */
2461         if(num == (count - 1U)) {
2462             if(ENET_DMA_TX == direction) {
2463                 /* configure transmit end of ring mode */
2464                 desc->status |= ENET_TDES0_TERM;
2465             } else {
2466                 /* configure receive end of ring mode */
2467                 desc->control_buffer_size |= ENET_RDES1_RERM;
2468             }
2469         }
2470     }
2471 }
2472 
2473 /*!
2474     \brief    receive a packet data with timestamp values to application buffer, when the DMA is in enhanced mode
2475     \param[in]  bufsize: the size of buffer which is the parameter in function
2476     \param[out] buffer: pointer to the application buffer
2477                 note -- if the input is NULL, user should copy data in application by himself
2478     \param[out] timestamp: pointer to the table which stores the timestamp high and low
2479                 note -- if the input is NULL, timestamp is ignored
2480     \retval     ErrStatus: SUCCESS or ERROR
2481 */
enet_ptpframe_receive_enhanced_mode(uint8_t * buffer,uint32_t bufsize,uint32_t timestamp[])2482 ErrStatus enet_ptpframe_receive_enhanced_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[])
2483 {
2484     uint32_t offset = 0U, size = 0U;
2485     uint32_t timeout = 0U;
2486     uint32_t rdes0_tsv_flag;
2487 
2488     /* the descriptor is busy due to own by the DMA */
2489     if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)) {
2490         return ERROR;
2491     }
2492 
2493     /* if buffer pointer is null, indicates that users has copied data in application */
2494     if(NULL != buffer) {
2495         /* if no error occurs, and the frame uses only one descriptor */
2496         if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) &&
2497                 ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) &&
2498                 ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))) {
2499             /* get the frame length except CRC */
2500             size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U;
2501 
2502             /* if is a type frame, and CRC is not included in forwarding frame */
2503             if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))) {
2504                 size = size + 4U;
2505             }
2506 
2507             /* to avoid situation that the frame size exceeds the buffer length */
2508             if(size > bufsize) {
2509                 return ERROR;
2510             }
2511 
2512             /* copy data from Rx buffer to application buffer */
2513             for(offset = 0; offset < size; offset++) {
2514                 (*(buffer + offset)) = (*(__IO uint8_t *)((dma_current_rxdesc->buffer1_addr) + offset));
2515             }
2516         } else {
2517             return ERROR;
2518         }
2519     }
2520 
2521     /* if timestamp pointer is null, indicates that users don't care timestamp in application */
2522     if(NULL != timestamp) {
2523         /* wait for ENET_RDES0_TSV flag to be set, the timestamp value is taken and
2524         write to the RDES6 and RDES7 */
2525         do {
2526             rdes0_tsv_flag = (dma_current_rxdesc->status & ENET_RDES0_TSV);
2527             timeout++;
2528         } while((RESET == rdes0_tsv_flag) && (timeout < ENET_DELAY_TO));
2529 
2530         /* return ERROR due to timeout */
2531         if(ENET_DELAY_TO == timeout) {
2532             return ERROR;
2533         }
2534 
2535         /* clear the ENET_RDES0_TSV flag */
2536         dma_current_rxdesc->status &= ~ENET_RDES0_TSV;
2537         /* get the timestamp value of the received frame */
2538         timestamp[0] = dma_current_rxdesc->timestamp_low;
2539         timestamp[1] = dma_current_rxdesc->timestamp_high;
2540     }
2541 
2542     /* enable reception, descriptor is owned by DMA */
2543     dma_current_rxdesc->status = ENET_RDES0_DAV;
2544 
2545     /* check Rx buffer unavailable flag status */
2546     if((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) {
2547         /* Clear RBU flag */
2548         ENET_DMA_STAT = ENET_DMA_STAT_RBU;
2549         /* resume DMA reception by writing to the RPEN register*/
2550         ENET_DMA_RPEN = 0;
2551     }
2552 
2553     /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */
2554     /* chained mode */
2555     if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) {
2556         dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_rxdesc->buffer2_next_desc_addr);
2557     } else {
2558         /* ring mode */
2559         if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) {
2560             /* if is the last descriptor in table, the next descriptor is the table header */
2561             dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR);
2562         } else {
2563             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
2564             dma_current_rxdesc = (enet_descriptors_struct *)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
2565         }
2566     }
2567 
2568     return SUCCESS;
2569 }
2570 
2571 /*!
2572     \brief    send data with timestamp values in application buffer as a transmit packet, when the DMA is in enhanced mode
2573     \param[in]  buffer: pointer on the application buffer
2574                 note -- if the input is NULL, user should copy data in application by himself
2575     \param[in]  length: the length of frame data to be transmitted
2576     \param[out] timestamp: pointer to the table which stores the timestamp high and low
2577                 note -- if the input is NULL, timestamp is ignored
2578     \retval     ErrStatus: SUCCESS or ERROR
2579 */
enet_ptpframe_transmit_enhanced_mode(uint8_t * buffer,uint32_t length,uint32_t timestamp[])2580 ErrStatus enet_ptpframe_transmit_enhanced_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[])
2581 {
2582     uint32_t offset = 0;
2583     uint32_t dma_tbu_flag, dma_tu_flag;
2584     uint32_t tdes0_ttmss_flag;
2585     uint32_t timeout = 0;
2586 
2587     /* the descriptor is busy due to own by the DMA */
2588     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) {
2589         return ERROR;
2590     }
2591 
2592     /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */
2593     if(length > ENET_MAX_FRAME_SIZE) {
2594         return ERROR;
2595     }
2596 
2597     /* if buffer pointer is null, indicates that users has handled data in application */
2598     if(NULL != buffer) {
2599         /* copy frame data from application buffer to Tx buffer */
2600         for(offset = 0; offset < length; offset++) {
2601             (*(__IO uint8_t *)((dma_current_txdesc->buffer1_addr) + offset)) = (*(buffer + offset));
2602         }
2603     }
2604     /* set the frame length */
2605     dma_current_txdesc->control_buffer_size = length;
2606     /* set the segment of frame, frame is transmitted in one descriptor */
2607     dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG;
2608     /* enable the DMA transmission */
2609     dma_current_txdesc->status |= ENET_TDES0_DAV;
2610 
2611     /* check Tx buffer unavailable flag status */
2612     dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU);
2613     dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU);
2614 
2615     if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)) {
2616         /* Clear TBU and TU flag */
2617         ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag);
2618         /* resume DMA transmission by writing to the TPEN register*/
2619         ENET_DMA_TPEN = 0;
2620     }
2621 
2622     /* if timestamp pointer is null, indicates that users don't care timestamp in application */
2623     if(NULL != timestamp) {
2624         /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */
2625         do {
2626             tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS);
2627             timeout++;
2628         } while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO));
2629 
2630         /* return ERROR due to timeout */
2631         if(ENET_DELAY_TO == timeout) {
2632             return ERROR;
2633         }
2634 
2635         /* clear the ENET_TDES0_TTMSS flag */
2636         dma_current_txdesc->status &= ~ENET_TDES0_TTMSS;
2637         /* get the timestamp value of the transmit frame */
2638         timestamp[0] = dma_current_txdesc->timestamp_low;
2639         timestamp[1] = dma_current_txdesc->timestamp_high;
2640     }
2641 
2642     /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table*/
2643     /* chained mode */
2644     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)) {
2645         dma_current_txdesc = (enet_descriptors_struct *)(dma_current_txdesc->buffer2_next_desc_addr);
2646     } else {
2647         /* ring mode */
2648         if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)) {
2649             /* if is the last descriptor in table, the next descriptor is the table header */
2650             dma_current_txdesc = (enet_descriptors_struct *)(ENET_DMA_TDTADDR);
2651         } else {
2652             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
2653             dma_current_txdesc = (enet_descriptors_struct *)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
2654         }
2655     }
2656 
2657     return SUCCESS;
2658 }
2659 
2660 #else
2661 
2662 /*!
2663     \brief    configure descriptor to work in normal mode
2664     \param[in]  none
2665     \param[out] none
2666     \retval     none
2667 */
enet_desc_select_normal_mode(void)2668 void enet_desc_select_normal_mode(void)
2669 {
2670     ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DFM;
2671 }
2672 
2673 /*!
2674     \brief    initialize the DMA Tx/Rx descriptors's parameters in normal chain mode with PTP function
2675     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
2676                 only one parameter can be selected which is shown as below
2677       \arg        ENET_DMA_TX: DMA Tx descriptors
2678       \arg        ENET_DMA_RX: DMA Rx descriptors
2679     \param[in]  desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table
2680     \param[out] none
2681     \retval     none
2682 */
enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction,enet_descriptors_struct * desc_ptptab)2683 void enet_ptp_normal_descriptors_chain_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab)
2684 {
2685     uint32_t num = 0U, count = 0U, maxsize = 0U;
2686     uint32_t desc_status = 0U, desc_bufsize = 0U;
2687     enet_descriptors_struct *desc, *desc_tab;
2688     uint8_t *buf;
2689 
2690     /* if want to initialize DMA Tx descriptors */
2691     if(ENET_DMA_TX == direction) {
2692         /* save a copy of the DMA Tx descriptors */
2693         desc_tab = txdesc_tab;
2694         buf = &tx_buff[0][0];
2695         count = ENET_TXBUF_NUM;
2696         maxsize = ENET_TXBUF_SIZE;
2697 
2698         /* select chain mode, and enable transmit timestamp function */
2699         desc_status = ENET_TDES0_TCHM | ENET_TDES0_TTSEN;
2700 
2701         /* configure DMA Tx descriptor table address register */
2702         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
2703         dma_current_txdesc = desc_tab;
2704         dma_current_ptp_txdesc = desc_ptptab;
2705     } else {
2706         /* if want to initialize DMA Rx descriptors */
2707         /* save a copy of the DMA Rx descriptors */
2708         desc_tab = rxdesc_tab;
2709         buf = &rx_buff[0][0];
2710         count = ENET_RXBUF_NUM;
2711         maxsize = ENET_RXBUF_SIZE;
2712 
2713         /* enable receiving */
2714         desc_status = ENET_RDES0_DAV;
2715         /* select receive chained mode and set buffer1 size */
2716         desc_bufsize = ENET_RDES1_RCHM | (uint32_t)ENET_RXBUF_SIZE;
2717 
2718         /* configure DMA Rx descriptor table address register */
2719         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
2720         dma_current_rxdesc = desc_tab;
2721         dma_current_ptp_rxdesc = desc_ptptab;
2722     }
2723 
2724     /* configure each descriptor */
2725     for(num = 0U; num < count; num++) {
2726         /* get the pointer to the next descriptor of the descriptor table */
2727         desc = desc_tab + num;
2728 
2729         /* configure descriptors */
2730         desc->status = desc_status;
2731         desc->control_buffer_size = desc_bufsize;
2732         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
2733 
2734         /* if is not the last descriptor */
2735         if(num < (count - 1U)) {
2736             /* configure the next descriptor address */
2737             desc->buffer2_next_desc_addr = (uint32_t)(desc_tab + num + 1U);
2738         } else {
2739             /* when it is the last descriptor, the next descriptor address
2740             equals to first descriptor address in descriptor table */
2741             desc->buffer2_next_desc_addr = (uint32_t)desc_tab;
2742         }
2743         /* set desc_ptptab equal to desc_tab */
2744         (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr;
2745         (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr;
2746     }
2747     /* when it is the last ptp descriptor, preserve the first descriptor
2748     address of desc_ptptab in ptp descriptor status */
2749     (&desc_ptptab[num - 1U])->status = (uint32_t)desc_ptptab;
2750 }
2751 
2752 /*!
2753     \brief    initialize the DMA Tx/Rx descriptors's parameters in normal ring mode with PTP function
2754     \param[in]  direction: the descriptors which users want to init, refer to enet_dmadirection_enum
2755                 only one parameter can be selected which is shown as below
2756       \arg        ENET_DMA_TX: DMA Tx descriptors
2757       \arg        ENET_DMA_RX: DMA Rx descriptors
2758     \param[in]  desc_ptptab: pointer to the first descriptor address of PTP Rx descriptor table
2759     \param[out] none
2760     \retval     none
2761 */
enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction,enet_descriptors_struct * desc_ptptab)2762 void enet_ptp_normal_descriptors_ring_init(enet_dmadirection_enum direction, enet_descriptors_struct *desc_ptptab)
2763 {
2764     uint32_t num = 0U, count = 0U, maxsize = 0U;
2765     uint32_t desc_status = 0U, desc_bufsize = 0U;
2766     enet_descriptors_struct *desc, *desc_tab;
2767     uint8_t *buf;
2768 
2769     /* configure descriptor skip length */
2770     ENET_DMA_BCTL &= ~ENET_DMA_BCTL_DPSL;
2771     ENET_DMA_BCTL |= DMA_BCTL_DPSL(0);
2772 
2773     /* if want to initialize DMA Tx descriptors */
2774     if(ENET_DMA_TX == direction) {
2775         /* save a copy of the DMA Tx descriptors */
2776         desc_tab = txdesc_tab;
2777         buf = &tx_buff[0][0];
2778         count = ENET_TXBUF_NUM;
2779         maxsize = ENET_TXBUF_SIZE;
2780 
2781         /* select ring mode, and enable transmit timestamp function */
2782         desc_status = ENET_TDES0_TTSEN;
2783 
2784         /* configure DMA Tx descriptor table address register */
2785         ENET_DMA_TDTADDR = (uint32_t)desc_tab;
2786         dma_current_txdesc = desc_tab;
2787         dma_current_ptp_txdesc = desc_ptptab;
2788     } else {
2789         /* if want to initialize DMA Rx descriptors */
2790         /* save a copy of the DMA Rx descriptors */
2791         desc_tab = rxdesc_tab;
2792         buf = &rx_buff[0][0];
2793         count = ENET_RXBUF_NUM;
2794         maxsize = ENET_RXBUF_SIZE;
2795 
2796         /* enable receiving */
2797         desc_status = ENET_RDES0_DAV;
2798         /* select receive ring mode and set buffer1 size */
2799         desc_bufsize = (uint32_t)ENET_RXBUF_SIZE;
2800 
2801         /* configure DMA Rx descriptor table address register */
2802         ENET_DMA_RDTADDR = (uint32_t)desc_tab;
2803         dma_current_rxdesc = desc_tab;
2804         dma_current_ptp_rxdesc = desc_ptptab;
2805     }
2806 
2807     /* configure each descriptor */
2808     for(num = 0U; num < count; num++) {
2809         /* get the pointer to the next descriptor of the descriptor table */
2810         desc = desc_tab + num;
2811 
2812         /* configure descriptors */
2813         desc->status = desc_status;
2814         desc->control_buffer_size = desc_bufsize;
2815         desc->buffer1_addr = (uint32_t)(&buf[num * maxsize]);
2816 
2817         /* when it is the last descriptor */
2818         if(num == (count - 1U)) {
2819             if(ENET_DMA_TX == direction) {
2820                 /* configure transmit end of ring mode */
2821                 desc->status |= ENET_TDES0_TERM;
2822             } else {
2823                 /* configure receive end of ring mode */
2824                 desc->control_buffer_size |= ENET_RDES1_RERM;
2825             }
2826         }
2827         /* set desc_ptptab equal to desc_tab */
2828         (&desc_ptptab[num])->buffer1_addr = desc->buffer1_addr;
2829         (&desc_ptptab[num])->buffer2_next_desc_addr = desc->buffer2_next_desc_addr;
2830     }
2831     /* when it is the last ptp descriptor, preserve the first descriptor
2832     address of desc_ptptab in ptp descriptor status */
2833     (&desc_ptptab[num - 1U])->status = (uint32_t)desc_ptptab;
2834 }
2835 
2836 /*!
2837     \brief    receive a packet data with timestamp values to application buffer, when the DMA is in normal mode
2838     \param[in]  bufsize: the size of buffer which is the parameter in function
2839     \param[out] buffer: pointer to the application buffer
2840                 note -- if the input is NULL, user should copy data in application by himself
2841     \param[out] timestamp: pointer to the table which stores the timestamp high and low
2842     \retval     ErrStatus: SUCCESS or ERROR
2843 */
enet_ptpframe_receive_normal_mode(uint8_t * buffer,uint32_t bufsize,uint32_t timestamp[])2844 ErrStatus enet_ptpframe_receive_normal_mode(uint8_t *buffer, uint32_t bufsize, uint32_t timestamp[])
2845 {
2846     uint32_t offset = 0U, size = 0U;
2847 
2848     /* the descriptor is busy due to own by the DMA */
2849     if((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_DAV)) {
2850         return ERROR;
2851     }
2852 
2853     /* if buffer pointer is null, indicates that users has copied data in application */
2854     if(NULL != buffer) {
2855         /* if no error occurs, and the frame uses only one descriptor */
2856         if(((uint32_t)RESET == (dma_current_rxdesc->status & ENET_RDES0_ERRS)) &&
2857                 ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_LDES)) &&
2858                 ((uint32_t)RESET != (dma_current_rxdesc->status & ENET_RDES0_FDES))) {
2859 
2860             /* get the frame length except CRC */
2861             size = GET_RDES0_FRML(dma_current_rxdesc->status) - 4U;
2862             /* if is a type frame, and CRC is not included in forwarding frame */
2863             if((RESET != (ENET_MAC_CFG & ENET_MAC_CFG_TFCD)) && (RESET != (dma_current_rxdesc->status & ENET_RDES0_FRMT))) {
2864                 size = size + 4U;
2865             }
2866 
2867             /* to avoid situation that the frame size exceeds the buffer length */
2868             if(size > bufsize) {
2869                 return ERROR;
2870             }
2871 
2872             /* copy data from Rx buffer to application buffer */
2873             for(offset = 0U; offset < size; offset++) {
2874                 (*(buffer + offset)) = (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_rxdesc->buffer1_addr) + offset));
2875             }
2876 
2877         } else {
2878             return ERROR;
2879         }
2880     }
2881     /* copy timestamp value from Rx descriptor to application array */
2882     timestamp[0] = dma_current_rxdesc->buffer1_addr;
2883     timestamp[1] = dma_current_rxdesc->buffer2_next_desc_addr;
2884 
2885     dma_current_rxdesc->buffer1_addr = dma_current_ptp_rxdesc ->buffer1_addr ;
2886     dma_current_rxdesc->buffer2_next_desc_addr = dma_current_ptp_rxdesc ->buffer2_next_desc_addr;
2887 
2888     /* enable reception, descriptor is owned by DMA */
2889     dma_current_rxdesc->status = ENET_RDES0_DAV;
2890 
2891     /* check Rx buffer unavailable flag status */
2892     if((uint32_t)RESET != (ENET_DMA_STAT & ENET_DMA_STAT_RBU)) {
2893         /* clear RBU flag */
2894         ENET_DMA_STAT = ENET_DMA_STAT_RBU;
2895         /* resume DMA reception by writing to the RPEN register*/
2896         ENET_DMA_RPEN = 0U;
2897     }
2898 
2899 
2900     /* update the current RxDMA descriptor pointer to the next decriptor in RxDMA decriptor table */
2901     /* chained mode */
2902     if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RCHM)) {
2903         dma_current_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->buffer2_next_desc_addr);
2904         /* if it is the last ptp descriptor */
2905         if(0U != dma_current_ptp_rxdesc->status) {
2906             /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
2907             dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status);
2908         } else {
2909             /* ponter to the next ptp descriptor */
2910             dma_current_ptp_rxdesc++;
2911         }
2912     } else {
2913         /* ring mode */
2914         if((uint32_t)RESET != (dma_current_rxdesc->control_buffer_size & ENET_RDES1_RERM)) {
2915             /* if is the last descriptor in table, the next descriptor is the table header */
2916             dma_current_rxdesc = (enet_descriptors_struct *)(ENET_DMA_RDTADDR);
2917             /* RDES2 and RDES3 will not be covered by buffer address, so do not need to preserve a new table,
2918             use the same table with RxDMA descriptor */
2919             dma_current_ptp_rxdesc = (enet_descriptors_struct *)(dma_current_ptp_rxdesc->status);
2920         } else {
2921             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
2922             dma_current_rxdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_rxdesc + ETH_DMARXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
2923             dma_current_ptp_rxdesc ++;
2924         }
2925     }
2926 
2927     return SUCCESS;
2928 }
2929 
2930 /*!
2931     \brief    send data with timestamp values in application buffer as a transmit packet, when the DMA is in normal mode
2932     \param[in]  buffer: pointer on the application buffer
2933                 note -- if the input is NULL, user should copy data in application by himself
2934     \param[in]  length: the length of frame data to be transmitted
2935     \param[out] timestamp: pointer to the table which stores the timestamp high and low
2936                 note -- if the input is NULL, timestamp is ignored
2937     \retval     ErrStatus: SUCCESS or ERROR
2938 */
enet_ptpframe_transmit_normal_mode(uint8_t * buffer,uint32_t length,uint32_t timestamp[])2939 ErrStatus enet_ptpframe_transmit_normal_mode(uint8_t *buffer, uint32_t length, uint32_t timestamp[])
2940 {
2941     uint32_t offset = 0U, timeout = 0U;
2942     uint32_t dma_tbu_flag, dma_tu_flag, tdes0_ttmss_flag;
2943 
2944     /* the descriptor is busy due to own by the DMA */
2945     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) {
2946         return ERROR;
2947     }
2948 
2949     /* only frame length no more than ENET_MAX_FRAME_SIZE is allowed */
2950     if(length > ENET_MAX_FRAME_SIZE) {
2951         return ERROR;
2952     }
2953 
2954     /* if buffer pointer is null, indicates that users has handled data in application */
2955     if(NULL != buffer) {
2956         /* copy frame data from application buffer to Tx buffer */
2957         for(offset = 0U; offset < length; offset++) {
2958             (*(__IO uint8_t *)(uint32_t)((dma_current_ptp_txdesc->buffer1_addr) + offset)) = (*(buffer + offset));
2959         }
2960     }
2961     /* set the frame length */
2962     dma_current_txdesc->control_buffer_size = (length & (uint32_t)0x1FFF);
2963     /* set the segment of frame, frame is transmitted in one descriptor */
2964     dma_current_txdesc->status |= ENET_TDES0_LSG | ENET_TDES0_FSG;
2965     /* enable the DMA transmission */
2966     dma_current_txdesc->status |= ENET_TDES0_DAV;
2967 
2968     /* check Tx buffer unavailable flag status */
2969     dma_tbu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TBU);
2970     dma_tu_flag = (ENET_DMA_STAT & ENET_DMA_STAT_TU);
2971 
2972     if((RESET != dma_tbu_flag) || (RESET != dma_tu_flag)) {
2973         /* clear TBU and TU flag */
2974         ENET_DMA_STAT = (dma_tbu_flag | dma_tu_flag);
2975         /* resume DMA transmission by writing to the TPEN register*/
2976         ENET_DMA_TPEN = 0U;
2977     }
2978 
2979     /* if timestamp pointer is null, indicates that users don't care timestamp in application */
2980     if(NULL != timestamp) {
2981         /* wait for ENET_TDES0_TTMSS flag to be set, a timestamp was captured */
2982         do {
2983             tdes0_ttmss_flag = (dma_current_txdesc->status & ENET_TDES0_TTMSS);
2984             timeout++;
2985         } while((RESET == tdes0_ttmss_flag) && (timeout < ENET_DELAY_TO));
2986 
2987         /* return ERROR due to timeout */
2988         if(ENET_DELAY_TO == timeout) {
2989             return ERROR;
2990         }
2991 
2992         /* clear the ENET_TDES0_TTMSS flag */
2993         dma_current_txdesc->status &= ~ENET_TDES0_TTMSS;
2994         /* get the timestamp value of the transmit frame */
2995         timestamp[0] = dma_current_txdesc->buffer1_addr;
2996         timestamp[1] = dma_current_txdesc->buffer2_next_desc_addr;
2997     }
2998     dma_current_txdesc->buffer1_addr = dma_current_ptp_txdesc ->buffer1_addr ;
2999     dma_current_txdesc->buffer2_next_desc_addr = dma_current_ptp_txdesc ->buffer2_next_desc_addr;
3000 
3001     /* update the current TxDMA descriptor pointer to the next decriptor in TxDMA decriptor table */
3002     /* chained mode */
3003     if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TCHM)) {
3004         dma_current_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->buffer2_next_desc_addr);
3005         /* if it is the last ptp descriptor */
3006         if(0U != dma_current_ptp_txdesc->status) {
3007             /* pointer back to the first ptp descriptor address in the desc_ptptab list address */
3008             dma_current_ptp_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->status);
3009         } else {
3010             /* ponter to the next ptp descriptor */
3011             dma_current_ptp_txdesc++;
3012         }
3013     } else {
3014         /* ring mode */
3015         if((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_TERM)) {
3016             /* if is the last descriptor in table, the next descriptor is the table header */
3017             dma_current_txdesc = (enet_descriptors_struct *)(ENET_DMA_TDTADDR);
3018             /* TDES2 and TDES3 will not be covered by buffer address, so do not need to preserve a new table,
3019             use the same table with TxDMA descriptor */
3020             dma_current_ptp_txdesc = (enet_descriptors_struct *)(dma_current_ptp_txdesc->status);
3021         } else {
3022             /* the next descriptor is the current address, add the descriptor size, and descriptor skip length */
3023             dma_current_txdesc = (enet_descriptors_struct *)(uint32_t)((uint32_t)dma_current_txdesc + ETH_DMATXDESC_SIZE + GET_DMA_BCTL_DPSL(ENET_DMA_BCTL));
3024             dma_current_ptp_txdesc ++;
3025         }
3026     }
3027     return SUCCESS;
3028 }
3029 
3030 #endif /* SELECT_DESCRIPTORS_ENHANCED_MODE */
3031 
3032 /*!
3033     \brief    wakeup frame filter register pointer reset
3034     \param[in]  none
3035     \param[out] none
3036     \retval     none
3037 */
enet_wum_filter_register_pointer_reset(void)3038 void enet_wum_filter_register_pointer_reset(void)
3039 {
3040     ENET_MAC_WUM |= ENET_MAC_WUM_WUFFRPR;
3041 }
3042 
3043 /*!
3044     \brief    set the remote wakeup frame registers
3045     \param[in]  pdata: pointer to buffer data which is written to remote wakeup frame registers (8 words total)
3046     \param[out] none
3047     \retval     none
3048 */
enet_wum_filter_config(uint32_t pdata[])3049 void enet_wum_filter_config(uint32_t pdata[])
3050 {
3051     uint32_t num = 0U;
3052 
3053     /* configure ENET_MAC_RWFF register */
3054     for(num = 0U; num < ETH_WAKEUP_REGISTER_LENGTH; num++) {
3055         ENET_MAC_RWFF = pdata[num];
3056     }
3057 }
3058 
3059 /*!
3060     \brief    enable wakeup management features
3061     \param[in]  feature: the wake up type which is selected
3062                 one or more parameters can be selected which are shown as below
3063       \arg        ENET_WUM_POWER_DOWN: power down mode
3064       \arg        ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception
3065       \arg        ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception
3066       \arg        ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame
3067     \param[out] none
3068     \retval     none
3069 */
enet_wum_feature_enable(uint32_t feature)3070 void enet_wum_feature_enable(uint32_t feature)
3071 {
3072     ENET_MAC_WUM |= feature;
3073 }
3074 
3075 /*!
3076     \brief    disable wakeup management features
3077     \param[in]  feature: the wake up type which is selected
3078                 one or more parameters can be selected which are shown as below
3079       \arg        ENET_WUM_MAGIC_PACKET_FRAME: enable a wakeup event due to magic packet reception
3080       \arg        ENET_WUM_WAKE_UP_FRAME: enable a wakeup event due to wakeup frame reception
3081       \arg        ENET_WUM_GLOBAL_UNICAST: any received unicast frame passed filter is considered to be a wakeup frame
3082     \param[out] none
3083     \retval     none
3084 */
enet_wum_feature_disable(uint32_t feature)3085 void enet_wum_feature_disable(uint32_t feature)
3086 {
3087     ENET_MAC_WUM &= (~feature);
3088 }
3089 
3090 /*!
3091     \brief    reset the MAC statistics counters
3092     \param[in]  none
3093     \param[out] none
3094     \retval     none
3095 */
enet_msc_counters_reset(void)3096 void enet_msc_counters_reset(void)
3097 {
3098     /* reset all counters */
3099     ENET_MSC_CTL |= ENET_MSC_CTL_CTR;
3100 }
3101 
3102 /*!
3103     \brief    enable the MAC statistics counter features
3104     \param[in]  feature: the feature of MAC statistics counter
3105                 one or more parameters can be selected which are shown as below
3106       \arg        ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover
3107       \arg        ENET_MSC_RESET_ON_READ: reset on read
3108       \arg        ENET_MSC_COUNTERS_FREEZE: MSC counter freeze
3109     \param[out] none
3110     \retval     none
3111 */
enet_msc_feature_enable(uint32_t feature)3112 void enet_msc_feature_enable(uint32_t feature)
3113 {
3114     ENET_MSC_CTL |= feature;
3115 }
3116 
3117 /*!
3118     \brief    disable the MAC statistics counter features
3119     \param[in]  feature: the feature of MAC statistics counter
3120                 one or more parameters can be selected which are shown as below
3121       \arg        ENET_MSC_COUNTER_STOP_ROLLOVER: counter stop rollover
3122       \arg        ENET_MSC_RESET_ON_READ: reset on read
3123       \arg        ENET_MSC_COUNTERS_FREEZE: MSC counter freeze
3124     \param[out] none
3125     \retval     none
3126 */
enet_msc_feature_disable(uint32_t feature)3127 void enet_msc_feature_disable(uint32_t feature)
3128 {
3129     ENET_MSC_CTL &= (~feature);
3130 }
3131 
3132 /*!
3133     \brief    configure MAC statistics counters preset mode
3134     \param[in]  mode: MSC counters preset mode, refer to enet_msc_preset_enum
3135                 only one parameter can be selected which is shown as below
3136       \arg        ENET_MSC_PRESET_NONE: do not preset MSC counter
3137       \arg        ENET_MSC_PRESET_HALF: preset all MSC counters to almost-half(0x7FFF FFF0) value
3138       \arg        ENET_MSC_PRESET_FULL: preset all MSC counters to almost-full(0xFFFF FFF0) value
3139     \param[out] none
3140     \retval     none
3141 */
enet_msc_counters_preset_config(enet_msc_preset_enum mode)3142 void enet_msc_counters_preset_config(enet_msc_preset_enum mode)
3143 {
3144     ENET_MSC_CTL &= ENET_MSC_PRESET_MASK;
3145     ENET_MSC_CTL |= (uint32_t)mode;
3146 }
3147 
3148 /*!
3149     \brief    get MAC statistics counter
3150     \param[in]  counter: MSC counters which is selected, refer to enet_msc_counter_enum
3151                 only one parameter can be selected which is shown as below
3152       \arg        ENET_MSC_TX_SCCNT: MSC transmitted good frames after a single collision counter
3153       \arg        ENET_MSC_TX_MSCCNT: MSC transmitted good frames after more than a single collision counter
3154       \arg        ENET_MSC_TX_TGFCNT: MSC transmitted good frames counter
3155       \arg        ENET_MSC_RX_RFCECNT: MSC received frames with CRC error counter
3156       \arg        ENET_MSC_RX_RFAECNT: MSC received frames with alignment error counter
3157       \arg        ENET_MSC_RX_RGUFCNT: MSC received good unicast frames counter
3158     \param[out] none
3159     \retval     the MSC counter value
3160 */
enet_msc_counters_get(enet_msc_counter_enum counter)3161 uint32_t enet_msc_counters_get(enet_msc_counter_enum counter)
3162 {
3163     uint32_t reval;
3164 
3165     reval = REG32((ENET + (uint32_t)counter));
3166 
3167     return reval;
3168 }
3169 
3170 /*!
3171     \brief    enable the PTP features
3172     \param[in]  feature: the feature of ENET PTP mode
3173                 one or more parameters can be selected which are shown as below
3174       \arg        ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames
3175       \arg        ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger
3176       \arg        ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot
3177       \arg        ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame
3178       \arg        ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame
3179       \arg        ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame
3180       \arg        ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame
3181     \param[out] none
3182     \retval     none
3183 */
enet_ptp_feature_enable(uint32_t feature)3184 void enet_ptp_feature_enable(uint32_t feature)
3185 {
3186     ENET_PTP_TSCTL |= feature;
3187 }
3188 
3189 /*!
3190     \brief    disable the PTP features
3191     \param[in]  feature: the feature of ENET PTP mode
3192                 one or more parameters can be selected which are shown as below
3193       \arg        ENET_RXTX_TIMESTAMP: timestamp function for transmit and receive frames
3194       \arg        ENET_PTP_TIMESTAMP_INT: timestamp interrupt trigger
3195       \arg        ENET_ALL_RX_TIMESTAMP: all received frames are taken snapshot
3196       \arg        ENET_NONTYPE_FRAME_SNAPSHOT: take snapshot when received non type frame
3197       \arg        ENET_IPV6_FRAME_SNAPSHOT: take snapshot for IPv6 frame
3198       \arg        ENET_IPV4_FRAME_SNAPSHOT: take snapshot for IPv4 frame
3199       \arg        ENET_PTP_FRAME_USE_MACADDRESS_FILTER: use MAC address1-3 to filter the PTP frame
3200     \param[out] none
3201     \retval     none
3202 */
enet_ptp_feature_disable(uint32_t feature)3203 void enet_ptp_feature_disable(uint32_t feature)
3204 {
3205     ENET_PTP_TSCTL &= ~feature;
3206 }
3207 
3208 /*!
3209     \brief    configure the PTP timestamp function
3210     \param[in]  func: the function of PTP timestamp
3211                 only one parameter can be selected which is shown as below
3212       \arg        ENET_CKNT_ORDINARY: type of ordinary clock node type for timestamp
3213       \arg        ENET_CKNT_BOUNDARY: type of boundary clock node type for timestamp
3214       \arg        ENET_CKNT_END_TO_END: type of end-to-end transparent clock node type for timestamp
3215       \arg        ENET_CKNT_PEER_TO_PEER: type of peer-to-peer transparent clock node type for timestamp
3216       \arg        ENET_PTP_ADDEND_UPDATE: addend register update
3217       \arg        ENET_PTP_SYSTIME_UPDATE: timestamp update
3218       \arg        ENET_PTP_SYSTIME_INIT: timestamp initialize
3219       \arg        ENET_PTP_FINEMODE: the system timestamp uses the fine method for updating
3220       \arg        ENET_PTP_COARSEMODE: the system timestamp uses the coarse method for updating
3221       \arg        ENET_SUBSECOND_DIGITAL_ROLLOVER: digital rollover mode
3222       \arg        ENET_SUBSECOND_BINARY_ROLLOVER: binary rollover mode
3223       \arg        ENET_SNOOPING_PTP_VERSION_2: version 2
3224       \arg        ENET_SNOOPING_PTP_VERSION_1: version 1
3225       \arg        ENET_EVENT_TYPE_MESSAGES_SNAPSHOT: only event type messages are taken snapshot
3226       \arg        ENET_ALL_TYPE_MESSAGES_SNAPSHOT: all type messages are taken snapshot except announce,
3227                                                    management and signaling message
3228       \arg        ENET_MASTER_NODE_MESSAGE_SNAPSHOT: snapshot is only take for master node message
3229       \arg        ENET_SLAVE_NODE_MESSAGE_SNAPSHOT: snapshot is only taken for slave node message
3230     \param[out] none
3231     \retval     ErrStatus: SUCCESS or ERROR
3232 */
enet_ptp_timestamp_function_config(enet_ptp_function_enum func)3233 ErrStatus enet_ptp_timestamp_function_config(enet_ptp_function_enum func)
3234 {
3235     uint32_t temp_config = 0U, temp_state = 0U;
3236     uint32_t timeout = 0U;
3237     ErrStatus enet_state = SUCCESS;
3238 
3239     switch(func) {
3240     case ENET_CKNT_ORDINARY:
3241     case ENET_CKNT_BOUNDARY:
3242     case ENET_CKNT_END_TO_END:
3243     case ENET_CKNT_PEER_TO_PEER:
3244         ENET_PTP_TSCTL &= ~ENET_PTP_TSCTL_CKNT;
3245         ENET_PTP_TSCTL |= (uint32_t)func;
3246         break;
3247     case ENET_PTP_ADDEND_UPDATE:
3248         /* this bit must be read as zero before application set it */
3249         do {
3250             temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSARU;
3251             timeout++;
3252         } while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
3253         /* return ERROR due to timeout */
3254         if(ENET_DELAY_TO == timeout) {
3255             enet_state = ERROR;
3256         } else {
3257             ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSARU;
3258         }
3259         break;
3260     case ENET_PTP_SYSTIME_UPDATE:
3261         /* both the TMSSTU and TMSSTI bits must be read as zero before application set this bit */
3262         do {
3263             temp_state = ENET_PTP_TSCTL & (ENET_PTP_TSCTL_TMSSTU | ENET_PTP_TSCTL_TMSSTI);
3264             timeout++;
3265         } while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
3266         /* return ERROR due to timeout */
3267         if(ENET_DELAY_TO == timeout) {
3268             enet_state = ERROR;
3269         } else {
3270             ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTU;
3271         }
3272         break;
3273     case ENET_PTP_SYSTIME_INIT:
3274         /* this bit must be read as zero before application set it */
3275         do {
3276             temp_state = ENET_PTP_TSCTL & ENET_PTP_TSCTL_TMSSTI;
3277             timeout++;
3278         } while((RESET != temp_state) && (timeout < ENET_DELAY_TO));
3279         /* return ERROR due to timeout */
3280         if(ENET_DELAY_TO == timeout) {
3281             enet_state = ERROR;
3282         } else {
3283             ENET_PTP_TSCTL |= ENET_PTP_TSCTL_TMSSTI;
3284         }
3285         break;
3286     default:
3287         temp_config = (uint32_t)func & (~BIT(31));
3288         if(RESET != ((uint32_t)func & BIT(31))) {
3289             ENET_PTP_TSCTL |= temp_config;
3290         } else {
3291             ENET_PTP_TSCTL &= ~temp_config;
3292         }
3293         break;
3294     }
3295 
3296     return enet_state;
3297 }
3298 
3299 /*!
3300     \brief    configure system time subsecond increment value
3301     \param[in]  subsecond: the value will be added to the subsecond value of system time(0x00000000 - 0x000000FF)
3302     \param[out] none
3303     \retval     none
3304 */
enet_ptp_subsecond_increment_config(uint32_t subsecond)3305 void enet_ptp_subsecond_increment_config(uint32_t subsecond)
3306 {
3307     ENET_PTP_SSINC = PTP_SSINC_STMSSI(subsecond);
3308 }
3309 
3310 /*!
3311     \brief    adjusting the clock frequency only in fine update mode
3312     \param[in]  add: the value will be added to the accumulator register to achieve time synchronization
3313     \param[out] none
3314     \retval     none
3315 */
enet_ptp_timestamp_addend_config(uint32_t add)3316 void enet_ptp_timestamp_addend_config(uint32_t add)
3317 {
3318     ENET_PTP_TSADDEND = add;
3319 }
3320 
3321 /*!
3322     \brief    initialize or add/subtract to second of the system time
3323     \param[in]  sign: timestamp update positive or negative sign
3324                 only one parameter can be selected which is shown as below
3325       \arg        ENET_PTP_ADD_TO_TIME: timestamp update value is added to system time
3326       \arg        ENET_PTP_SUBSTRACT_FROM_TIME: timestamp update value is subtracted from system time
3327     \param[in]  second: initializing or adding/subtracting to second of the system time
3328     \param[in]  subsecond: the current subsecond of the system time
3329                 with 0.46 ns accuracy if required accuracy is 20 ns
3330     \param[out] none
3331     \retval     none
3332 */
enet_ptp_timestamp_update_config(uint32_t sign,uint32_t second,uint32_t subsecond)3333 void enet_ptp_timestamp_update_config(uint32_t sign, uint32_t second, uint32_t subsecond)
3334 {
3335     ENET_PTP_TSUH = second;
3336     ENET_PTP_TSUL = sign | PTP_TSUL_TMSUSS(subsecond);
3337 }
3338 
3339 /*!
3340     \brief    configure the expected target time
3341     \param[in]  second: the expected target second time
3342     \param[in]  nanosecond: the expected target nanosecond time (signed)
3343     \param[out] none
3344     \retval     none
3345 */
enet_ptp_expected_time_config(uint32_t second,uint32_t nanosecond)3346 void enet_ptp_expected_time_config(uint32_t second, uint32_t nanosecond)
3347 {
3348     ENET_PTP_ETH = second;
3349     ENET_PTP_ETL = nanosecond;
3350 }
3351 
3352 /*!
3353     \brief    get the current system time
3354     \param[in]  none
3355     \param[out] systime_struct: pointer to a enet_ptp_systime_struct structure which contains
3356                 parameters of PTP system time
3357                 members of the structure and the member values are shown as below:
3358                   second: 0x0 - 0xFFFF FFFF
3359                   subsecond: 0x0 - 0x7FFF FFFF
3360                   sign: ENET_PTP_TIME_POSITIVE, ENET_PTP_TIME_NEGATIVE
3361     \retval     none
3362 */
enet_ptp_system_time_get(enet_ptp_systime_struct * systime_struct)3363 void enet_ptp_system_time_get(enet_ptp_systime_struct *systime_struct)
3364 {
3365     uint32_t temp_sec = 0U, temp_subs = 0U;
3366 
3367     /* get the value of sysytem time registers */
3368     temp_sec = (uint32_t)ENET_PTP_TSH;
3369     temp_subs = (uint32_t)ENET_PTP_TSL;
3370 
3371     /* get sysytem time and construct the enet_ptp_systime_struct structure */
3372     systime_struct->second = temp_sec;
3373     systime_struct->subsecond = GET_PTP_TSL_STMSS(temp_subs);
3374     systime_struct->sign = GET_PTP_TSL_STS(temp_subs);
3375 }
3376 
3377 /*!
3378     \brief    configure the PPS output frequency
3379     \param[in]  freq: PPS output frequency
3380                 only one parameter can be selected which is shown as below
3381       \arg        ENET_PPSOFC_1HZ: PPS output 1Hz frequency
3382       \arg        ENET_PPSOFC_2HZ: PPS output 2Hz frequency
3383       \arg        ENET_PPSOFC_4HZ: PPS output 4Hz frequency
3384       \arg        ENET_PPSOFC_8HZ: PPS output 8Hz frequency
3385       \arg        ENET_PPSOFC_16HZ: PPS output 16Hz frequency
3386       \arg        ENET_PPSOFC_32HZ: PPS output 32Hz frequency
3387       \arg        ENET_PPSOFC_64HZ: PPS output 64Hz frequency
3388       \arg        ENET_PPSOFC_128HZ: PPS output 128Hz frequency
3389       \arg        ENET_PPSOFC_256HZ: PPS output 256Hz frequency
3390       \arg        ENET_PPSOFC_512HZ: PPS output 512Hz frequency
3391       \arg        ENET_PPSOFC_1024HZ: PPS output 1024Hz frequency
3392       \arg        ENET_PPSOFC_2048HZ: PPS output 2048Hz frequency
3393       \arg        ENET_PPSOFC_4096HZ: PPS output 4096Hz frequency
3394       \arg        ENET_PPSOFC_8192HZ: PPS output 8192Hz frequency
3395       \arg        ENET_PPSOFC_16384HZ: PPS output 16384Hz frequency
3396       \arg        ENET_PPSOFC_32768HZ: PPS output 32768Hz frequency
3397     \param[out] none
3398     \retval     none
3399 */
enet_ptp_pps_output_frequency_config(uint32_t freq)3400 void enet_ptp_pps_output_frequency_config(uint32_t freq)
3401 {
3402     ENET_PTP_PPSCTL = freq;
3403 }
3404 
3405 /*!
3406     \brief    reset the ENET initpara struct, call it before using enet_initpara_config()
3407     \param[in]  none
3408     \param[out] none
3409     \retval     none
3410 */
enet_initpara_reset(void)3411 void enet_initpara_reset(void)
3412 {
3413     enet_initpara.option_enable = 0U;
3414     enet_initpara.forward_frame = 0U;
3415     enet_initpara.dmabus_mode = 0U;
3416     enet_initpara.dma_maxburst = 0U;
3417     enet_initpara.dma_arbitration = 0U;
3418     enet_initpara.store_forward_mode = 0U;
3419     enet_initpara.dma_function = 0U;
3420     enet_initpara.vlan_config = 0U;
3421     enet_initpara.flow_control = 0U;
3422     enet_initpara.hashtable_high = 0U;
3423     enet_initpara.hashtable_low = 0U;
3424     enet_initpara.framesfilter_mode = 0U;
3425     enet_initpara.halfduplex_param = 0U;
3426     enet_initpara.timer_config = 0U;
3427     enet_initpara.interframegap = 0U;
3428 }
3429 
3430 /*!
3431     \brief    initialize ENET peripheral with generally concerned parameters, call it by enet_init()
3432     \param[in]  none
3433     \param[out] none
3434     \retval     none
3435 */
enet_default_init(void)3436 static void enet_default_init(void)
3437 {
3438     uint32_t reg_value = 0U;
3439 
3440     /* MAC */
3441     /* configure ENET_MAC_CFG register */
3442     reg_value = ENET_MAC_CFG;
3443     reg_value &= MAC_CFG_MASK;
3444     reg_value |= ENET_WATCHDOG_ENABLE | ENET_JABBER_ENABLE | ENET_INTERFRAMEGAP_96BIT \
3445                  | ENET_SPEEDMODE_10M | ENET_MODE_HALFDUPLEX | ENET_LOOPBACKMODE_DISABLE \
3446                  | ENET_CARRIERSENSE_ENABLE | ENET_RECEIVEOWN_ENABLE \
3447                  | ENET_RETRYTRANSMISSION_ENABLE | ENET_BACKOFFLIMIT_10 \
3448                  | ENET_DEFERRALCHECK_DISABLE \
3449                  | ENET_TYPEFRAME_CRC_DROP_DISABLE \
3450                  | ENET_AUTO_PADCRC_DROP_DISABLE \
3451                  | ENET_CHECKSUMOFFLOAD_DISABLE;
3452     ENET_MAC_CFG = reg_value;
3453 
3454     /* configure ENET_MAC_FRMF register */
3455     ENET_MAC_FRMF = ENET_SRC_FILTER_DISABLE | ENET_DEST_FILTER_INVERSE_DISABLE \
3456                     | ENET_MULTICAST_FILTER_PERFECT | ENET_UNICAST_FILTER_PERFECT \
3457                     | ENET_PCFRM_PREVENT_ALL | ENET_BROADCASTFRAMES_ENABLE \
3458                     | ENET_PROMISCUOUS_DISABLE | ENET_RX_FILTER_ENABLE;
3459 
3460     /* configure ENET_MAC_HLH, ENET_MAC_HLL register */
3461     ENET_MAC_HLH = 0x0U;
3462 
3463     ENET_MAC_HLL = 0x0U;
3464 
3465     /* configure ENET_MAC_FCTL, ENET_MAC_FCTH register */
3466     reg_value = ENET_MAC_FCTL;
3467     reg_value &= MAC_FCTL_MASK;
3468     reg_value |= MAC_FCTL_PTM(0) | ENET_ZERO_QUANTA_PAUSE_DISABLE \
3469                  | ENET_PAUSETIME_MINUS4 | ENET_UNIQUE_PAUSEDETECT \
3470                  | ENET_RX_FLOWCONTROL_DISABLE | ENET_TX_FLOWCONTROL_DISABLE;
3471     ENET_MAC_FCTL = reg_value;
3472 
3473     /* configure ENET_MAC_VLT register */
3474     ENET_MAC_VLT = ENET_VLANTAGCOMPARISON_16BIT | MAC_VLT_VLTI(0);
3475 
3476     /* DMA */
3477     /* configure ENET_DMA_CTL register */
3478     reg_value = ENET_DMA_CTL;
3479     reg_value &= DMA_CTL_MASK;
3480     reg_value |= ENET_TCPIP_CKSUMERROR_DROP | ENET_RX_MODE_STOREFORWARD \
3481                  | ENET_FLUSH_RXFRAME_ENABLE | ENET_TX_MODE_STOREFORWARD \
3482                  | ENET_TX_THRESHOLD_64BYTES | ENET_RX_THRESHOLD_64BYTES \
3483                  | ENET_SECONDFRAME_OPT_DISABLE;
3484     ENET_DMA_CTL = reg_value;
3485 
3486     /* configure ENET_DMA_BCTL register */
3487     reg_value = ENET_DMA_BCTL;
3488     reg_value &= DMA_BCTL_MASK;
3489     reg_value = ENET_ADDRESS_ALIGN_ENABLE | ENET_ARBITRATION_RXTX_2_1 \
3490                 | ENET_RXDP_32BEAT | ENET_PGBL_32BEAT | ENET_RXTX_DIFFERENT_PGBL \
3491                 | ENET_FIXED_BURST_ENABLE | ENET_MIXED_BURST_DISABLE \
3492                 | ENET_NORMAL_DESCRIPTOR;
3493     ENET_DMA_BCTL = reg_value;
3494 }
3495 
3496 #ifndef USE_DELAY
3497 /*!
3498     \brief    insert a delay time
3499     \param[in]  ncount: specifies the delay time length
3500     \param[out] none
3501     \param[out] none
3502 */
enet_delay(uint32_t ncount)3503 static void enet_delay(uint32_t ncount)
3504 {
3505     __IO uint32_t delay_time = 0U;
3506 
3507     for(delay_time = ncount; delay_time != 0U; delay_time--) {
3508     }
3509 }
3510 #endif /* USE_DELAY */
3511