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