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