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