| /** |
| * \file |
| * |
| * \brief GMAC (Ethernet MAC) driver for SAM. |
| * |
| * Copyright (c) 2013 Atmel Corporation. All rights reserved. |
| * |
| * \asf_license_start |
| * |
| * \page License |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * 3. The name of Atmel may not be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * 4. This software may only be redistributed and used in connection with an |
| * Atmel microcontroller product. |
| * |
| * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE |
| * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| * |
| * \asf_license_stop |
| * |
| */ |
| |
| #ifndef GMAC_H_INCLUDED |
| #define GMAC_H_INCLUDED |
| |
| #include "compiler.h" |
| |
| /// @cond 0 |
| /**INDENT-OFF**/ |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| /**INDENT-ON**/ |
| /// @endcond |
| |
| /** The buffer addresses written into the descriptors must be aligned, so the |
| last few bits are zero. These bits have special meaning for the GMAC |
| peripheral and cannot be used as part of the address. */ |
| #define GMAC_RXD_ADDR_MASK 0xFFFFFFFC |
| #define GMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */ |
| #define GMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */ |
| |
| #define GMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */ |
| #define GMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */ |
| #define GMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */ |
| #define GMAC_RXD_ADDR_FOUND (1ul << 27) /**< Specific address match found */ |
| #define GMAC_RXD_ADDR (3ul << 25) /**< Address match */ |
| #define GMAC_RXD_RXCOEN (1ul << 24) /**< RXCOEN related function */ |
| #define GMAC_RXD_TYPE (3ul << 22) /**< Type ID match */ |
| #define GMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */ |
| #define GMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */ |
| #define GMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */ |
| #define GMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */ |
| #define GMAC_RXD_EOF (1ul << 15) /**< End of frame */ |
| #define GMAC_RXD_SOF (1ul << 14) /**< Start of frame */ |
| #define GMAC_RXD_FCS (1ul << 13) /**< Frame check sequence */ |
| #define GMAC_RXD_OFFSET_MASK /**< Receive buffer offset */ |
| #define GMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */ |
| #define GMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */ |
| |
| #define GMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */ |
| #define GMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */ |
| #define GMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */ |
| #define GMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */ |
| #define GMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */ |
| #define GMAC_TXD_LATE (1ul << 26) /**< Late collision,transmit error */ |
| #define GMAC_TXD_CHECKSUM_ERROR (7ul << 20) /**< Checksum error */ |
| #define GMAC_TXD_NOCRC (1ul << 16) /**< No CRC */ |
| #define GMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */ |
| #define GMAC_TXD_LEN_MASK (0x1FFF) /**< Length of buffer */ |
| |
| /** The MAC can support frame lengths up to 1536 bytes */ |
| #define GMAC_FRAME_LENTGH_MAX 1536 |
| |
| #define GMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */ |
| #define GMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */ |
| |
| /** GMAC clock speed */ |
| #define GMAC_MCK_SPEED_240MHZ (240*1000*1000) |
| #define GMAC_MCK_SPEED_160MHZ (160*1000*1000) |
| #define GMAC_MCK_SPEED_120MHZ (120*1000*1000) |
| #define GMAC_MCK_SPEED_80MHZ (80*1000*1000) |
| #define GMAC_MCK_SPEED_40MHZ (40*1000*1000) |
| #define GMAC_MCK_SPEED_20MHZ (20*1000*1000) |
| |
| /** GMAC maintain code default value*/ |
| #define GMAC_MAN_CODE_VALUE (10) |
| |
| /** GMAC maintain start of frame default value*/ |
| #define GMAC_MAN_SOF_VALUE (1) |
| |
| /** GMAC maintain read/write*/ |
| #define GMAC_MAN_RW_TYPE (2) |
| |
| /** GMAC maintain read only*/ |
| #define GMAC_MAN_READ_ONLY (1) |
| |
| /** GMAC address length */ |
| #define GMAC_ADDR_LENGTH (6) |
| |
| |
| #define GMAC_DUPLEX_HALF 0 |
| #define GMAC_DUPLEX_FULL 1 |
| |
| #define GMAC_SPEED_10M 0 |
| #define GMAC_SPEED_100M 1 |
| |
| /** |
| * \brief Return codes for GMAC APIs. |
| */ |
| typedef enum { |
| GMAC_OK = 0, /** 0 Operation OK */ |
| GMAC_TIMEOUT = 1, /** 1 GMAC operation timeout */ |
| GMAC_TX_BUSY, /** 2 TX in progress */ |
| GMAC_RX_NULL, /** 3 No data received */ |
| GMAC_SIZE_TOO_SMALL, /** 4 Buffer size not enough */ |
| GMAC_PARAM, /** 5 Parameter error, TX packet invalid or RX size too small */ |
| GMAC_INVALID = 0xFF, /* Invalid */ |
| } gmac_status_t; |
| |
| /** |
| * \brief Media Independent Interface (MII) type. |
| */ |
| typedef enum { |
| GMAC_PHY_MII = 0, /** MII mode */ |
| GMAC_PHY_RMII = 1, /** Reduced MII mode */ |
| GMAC_PHY_INVALID = 0xFF, /* Invalid mode*/ |
| } gmac_mii_mode_t; |
| |
| /** Receive buffer descriptor struct */ |
| COMPILER_PACK_SET(8) |
| typedef struct gmac_rx_descriptor { |
| union gmac_rx_addr { |
| uint32_t val; |
| struct gmac_rx_addr_bm { |
| uint32_t b_ownership:1, /**< User clear, GMAC sets this to 1 once it has successfully written a frame to memory */ |
| b_wrap:1, /**< Marks last descriptor in receive buffer */ |
| addr_dw:30; /**< Address in number of DW */ |
| } bm; |
| } addr; /**< Address, Wrap & Ownership */ |
| union gmac_rx_status { |
| uint32_t val; |
| struct gmac_rx_status_bm { |
| uint32_t len:13, /** 0..12 Length of frame including FCS */ |
| b_fcs:1, /** 13 Receive buffer offset, bits 13:12 of frame length for jumbo frame */ |
| b_sof:1, /** 14 Start of frame */ |
| b_eof:1, /** 15 End of frame */ |
| b_cfi:1, /** 16 Concatenation Format Indicator */ |
| vlan_priority:3, /** 17..19 VLAN priority (if VLAN detected) */ |
| b_priority_detected:1, /** 20 Priority tag detected */ |
| b_vlan_detected:1, /** 21 VLAN tag detected */ |
| b_type_id_match:2, /** 22..23 Type ID match */ |
| b_checksumoffload:1, /** 24 Checksum offload specific function */ |
| b_addrmatch:2, /** 25..26 Address register match */ |
| b_ext_addr_match:1, /** 27 External address match found */ |
| reserved:1, /** 28 */ |
| b_uni_hash_match:1, /** 29 Unicast hash match */ |
| b_multi_hash_match:1, /** 30 Multicast hash match */ |
| b_boardcast_detect:1; /** 31 Global broadcast address detected */ |
| } bm; |
| } status; |
| } gmac_rx_descriptor_t; |
| |
| /** Transmit buffer descriptor struct */ |
| COMPILER_PACK_SET(8) |
| typedef struct gmac_tx_descriptor { |
| uint32_t addr; |
| union gmac_tx_status { |
| uint32_t val; |
| struct gmac_tx_status_bm { |
| uint32_t len:14, /** 0..13 Length of buffer */ |
| reserved:1, /** 14 */ |
| b_last_buffer:1, /** 15 Last buffer (in the current frame) */ |
| b_no_crc:1, /** 16 No CRC */ |
| reserved1:3, /** 17..19 */ |
| b_checksumoffload:3, /** 20..22 Transmit checksum generation offload errors */ |
| reserved2:3, /** 23..25 */ |
| b_lco:1, /** 26 Late collision, transmit error detected */ |
| b_exhausted:1, /** 27 Buffer exhausted in mid frame */ |
| b_underrun:1, /** 28 Transmit underrun */ |
| b_error:1, /** 29 Retry limit exceeded, error detected */ |
| b_wrap:1, /** 30 Marks last descriptor in TD list */ |
| b_used:1; /** 31 User clear, GMAC sets this to 1 once a frame has been successfully transmitted */ |
| } bm; |
| } status; |
| } gmac_tx_descriptor_t; |
| |
| COMPILER_PACK_RESET() |
| |
| /** |
| * \brief Input parameters when initializing the gmac module mode. |
| */ |
| typedef struct gmac_options { |
| /* Enable/Disable CopyAllFrame */ |
| uint8_t uc_copy_all_frame; |
| /* Enable/Disable NoBroadCast */ |
| uint8_t uc_no_boardcast; |
| /* MAC address */ |
| uint8_t uc_mac_addr[GMAC_ADDR_LENGTH]; |
| } gmac_options_t; |
| |
| /** RX callback */ |
| typedef void (*gmac_dev_tx_cb_t) (uint32_t ul_status); |
| /** Wakeup callback */ |
| typedef void (*gmac_dev_wakeup_cb_t) (void); |
| |
| /** |
| * GMAC driver structure. |
| */ |
| typedef struct gmac_device { |
| |
| /** Pointer to HW register base */ |
| Gmac *p_hw; |
| /** |
| * Pointer to allocated TX buffer. |
| * Section 3.6 of AMBA 2.0 spec states that burst should not cross |
| * 1K Boundaries. |
| * Receive buffer manager writes are burst of 2 words => 3 lsb bits |
| * of the address shall be set to 0. |
| */ |
| uint8_t *p_tx_buffer; |
| /** Pointer to allocated RX buffer */ |
| uint8_t *p_rx_buffer; |
| /** Pointer to Rx TDs (must be 8-byte aligned) */ |
| gmac_rx_descriptor_t *p_rx_dscr; |
| /** Pointer to Tx TDs (must be 8-byte aligned) */ |
| gmac_tx_descriptor_t *p_tx_dscr; |
| /** Optional callback to be invoked once a frame has been received */ |
| gmac_dev_tx_cb_t func_rx_cb; |
| #if( GMAC_USES_WAKEUP_CALLBACK ) |
| /** Optional callback to be invoked once several TDs have been released */ |
| gmac_dev_wakeup_cb_t func_wakeup_cb; |
| #endif |
| #if( GMAC_USES_TX_CALLBACK != 0 ) |
| /** Optional callback list to be invoked once TD has been processed */ |
| gmac_dev_tx_cb_t *func_tx_cb_list; |
| #endif |
| /** RX TD list size */ |
| uint32_t ul_rx_list_size; |
| /** RX index for current processing TD */ |
| uint32_t ul_rx_idx; |
| /** TX TD list size */ |
| uint32_t ul_tx_list_size; |
| /** Circular buffer head pointer by upper layer (buffer to be sent) */ |
| int32_t l_tx_head; |
| /** Circular buffer tail pointer incremented by handlers (buffer sent) */ |
| int32_t l_tx_tail; |
| |
| /** Number of free TD before wakeup callback is invoked */ |
| uint32_t uc_wakeup_threshold; |
| } gmac_device_t; |
| |
| /** |
| * \brief Write network control value. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_ncr Network control value. |
| */ |
| static inline void gmac_network_control(Gmac* p_gmac, uint32_t ul_ncr) |
| { |
| p_gmac->GMAC_NCR = ul_ncr; |
| } |
| |
| /** |
| * \brief Get network control value. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| |
| static inline uint32_t gmac_get_network_control(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_NCR; |
| } |
| |
| /** |
| * \brief Enable/Disable GMAC receive. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable GMAC receiver, else to enable it. |
| */ |
| static inline void gmac_enable_receive(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_RXEN; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_RXEN; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable GMAC transmit. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable GMAC transmit, else to enable it. |
| */ |
| static inline void gmac_enable_transmit(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_TXEN; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_TXEN; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable GMAC management. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable GMAC management, else to enable it. |
| */ |
| static inline void gmac_enable_management(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_MPE; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_MPE; |
| } |
| } |
| |
| /** |
| * \brief Clear all statistics registers. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_clear_statistics(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT; |
| } |
| |
| /** |
| * \brief Increase all statistics registers. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_increase_statistics(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_INCSTAT; |
| } |
| |
| /** |
| * \brief Enable/Disable statistics registers writing. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the statistics registers writing, else to enable it. |
| */ |
| static inline void gmac_enable_statistics_write(Gmac* p_gmac, |
| uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_WESTAT; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT; |
| } |
| } |
| |
| /** |
| * \brief In half-duplex mode, forces collisions on all received frames. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the back pressure, else to enable it. |
| */ |
| static inline void gmac_enable_back_pressure(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_BP; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_BP; |
| } |
| } |
| |
| /** |
| * \brief Start transmission. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_start_transmission(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_TSTART; |
| } |
| |
| /** |
| * \brief Halt transmission. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_halt_transmission(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_THALT; |
| } |
| |
| /** |
| * \brief Transmit pause frame. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_tx_pause_frame(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_TXPF; |
| } |
| |
| /** |
| * \brief Transmit zero quantum pause frame. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_tx_pause_zero_quantum_frame(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_TXZQPF; |
| } |
| |
| /** |
| * \brief Read snapshot. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_read_snapshot(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_RDS; |
| } |
| |
| /** |
| * \brief Store receivetime stamp to memory. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to normal operation, else to enable the store. |
| */ |
| static inline void gmac_store_rx_time_stamp(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_SRTSM; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_SRTSM; |
| } |
| } |
| |
| /** |
| * \brief Enable PFC priority-based pause reception. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 1 to set the reception, 0 to disable. |
| */ |
| static inline void gmac_enable_pfc_pause_frame(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCR |= GMAC_NCR_ENPBPR; |
| } else { |
| p_gmac->GMAC_NCR &= ~GMAC_NCR_ENPBPR; |
| } |
| } |
| |
| /** |
| * \brief Transmit PFC priority-based pause reception. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_transmit_pfc_pause_frame(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_TXPBPF; |
| } |
| |
| /** |
| * \brief Flush next packet. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_flush_next_packet(Gmac* p_gmac) |
| { |
| p_gmac->GMAC_NCR |= GMAC_NCR_FNP; |
| } |
| |
| /** |
| * \brief Set up network configuration register. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_cfg Network configuration value. |
| */ |
| static inline void gmac_set_configure(Gmac* p_gmac, uint32_t ul_cfg) |
| { |
| p_gmac->GMAC_NCFGR = ul_cfg; |
| } |
| |
| /** |
| * \brief Get network configuration. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Network configuration. |
| */ |
| static inline uint32_t gmac_get_configure(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_NCFGR; |
| } |
| |
| |
| /* Get and set DMA Configuration Register */ |
| static inline void gmac_set_dma(Gmac* p_gmac, uint32_t ul_cfg) |
| { |
| p_gmac->GMAC_DCFGR = ul_cfg; |
| } |
| |
| static inline uint32_t gmac_get_dma(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_DCFGR; |
| } |
| |
| /** |
| * \brief Set speed. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps. |
| */ |
| static inline void gmac_set_speed(Gmac* p_gmac, uint8_t uc_speed) |
| { |
| if (uc_speed) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable Full-Duplex mode. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the Full-Duplex mode, else to enable it. |
| */ |
| static inline void gmac_enable_full_duplex(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_FD; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable Copy(Receive) All Valid Frames. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable copying all valid frames, else to enable it. |
| */ |
| static inline void gmac_enable_copy_all(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_CAF; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_CAF; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable jumbo frames (up to 10240 bytes). |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the jumbo frames, else to enable it. |
| */ |
| static inline void gmac_enable_jumbo_frames(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_JFRAME; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_JFRAME; |
| } |
| } |
| |
| /** |
| * \brief Disable/Enable broadcast receiving. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 1 to disable the broadcast, else to enable it. |
| */ |
| static inline void gmac_disable_broadcast(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_NBC; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_NBC; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable multicast hash. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the multicast hash, else to enable it. |
| */ |
| static inline void gmac_enable_multicast_hash(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_UNIHEN; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable big frames (over 1518, up to 1536). |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable big frames else to enable it. |
| */ |
| static inline void gmac_enable_big_frame(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_MAXFS; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_MAXFS; |
| } |
| } |
| |
| /** |
| * \brief Set MDC clock divider. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_mck GMAC MCK. |
| * |
| * \return GMAC_OK if successfully. |
| */ |
| static inline uint8_t gmac_set_mdc_clock(Gmac* p_gmac, uint32_t ul_mck) |
| { |
| uint32_t ul_clk; |
| |
| if (ul_mck > GMAC_MCK_SPEED_240MHZ) { |
| return GMAC_INVALID; |
| } else if (ul_mck > GMAC_MCK_SPEED_160MHZ) { |
| ul_clk = GMAC_NCFGR_CLK_MCK_96; |
| } else if (ul_mck > GMAC_MCK_SPEED_120MHZ) { |
| ul_clk = GMAC_NCFGR_CLK_MCK_64; |
| } else if (ul_mck > GMAC_MCK_SPEED_80MHZ) { |
| ul_clk = GMAC_NCFGR_CLK_MCK_48; |
| } else if (ul_mck > GMAC_MCK_SPEED_40MHZ) { |
| ul_clk = GMAC_NCFGR_CLK_MCK_32; |
| } else if (ul_mck > GMAC_MCK_SPEED_20MHZ) { |
| ul_clk = GMAC_NCFGR_CLK_MCK_16; |
| } else { |
| ul_clk = GMAC_NCFGR_CLK_MCK_8; |
| } |
| ; |
| p_gmac->GMAC_NCFGR = (p_gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | ul_clk; |
| return GMAC_OK; |
| } |
| |
| /** |
| * \brief Enable/Disable retry test. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the GMAC receiver, else to enable it. |
| */ |
| static inline void gmac_enable_retry_test(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RTY; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RTY; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable pause (when a valid pause frame is received). |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable pause frame, else to enable it. |
| */ |
| static inline void gmac_enable_pause_frame(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_PEN; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_PEN; |
| } |
| } |
| |
| /** |
| * \brief Set receive buffer offset to 0 ~ 3. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline void gmac_set_rx_buffer_offset(Gmac* p_gmac, uint8_t uc_offset) |
| { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RXBUFO_Msk; |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(uc_offset); |
| } |
| |
| /** |
| * \brief Enable/Disable receive length field checking. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable receive length field checking, else to enable it. |
| */ |
| static inline void gmac_enable_rx_length_check(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_LFERD; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_LFERD; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable discarding FCS field of received frames. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it. |
| */ |
| static inline void gmac_enable_discard_fcs(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_RFCS; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_RFCS; |
| } |
| } |
| |
| |
| /** |
| * \brief Enable/Disable frames to be received in half-duplex mode |
| * while transmitting. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable the received in half-duplex mode, else to enable it. |
| */ |
| static inline void gmac_enable_efrhd(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_EFRHD; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_EFRHD; |
| } |
| } |
| |
| /** |
| * \brief Enable/Disable ignore RX FCS. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_enable 0 to disable ignore RX FCS, else to enable it. |
| */ |
| static inline void gmac_enable_ignore_rx_fcs(Gmac* p_gmac, uint8_t uc_enable) |
| { |
| if (uc_enable) { |
| p_gmac->GMAC_NCFGR |= GMAC_NCFGR_IRXFCS; |
| } else { |
| p_gmac->GMAC_NCFGR &= ~GMAC_NCFGR_IRXFCS; |
| } |
| } |
| |
| /** |
| * \brief Get Network Status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Network status. |
| */ |
| static inline uint32_t gmac_get_status(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_NSR; |
| } |
| |
| /** |
| * \brief Get MDIO IN pin status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return MDIO IN pin status. |
| */ |
| static inline uint8_t gmac_get_MDIO(Gmac* p_gmac) |
| { |
| return ((p_gmac->GMAC_NSR & GMAC_NSR_MDIO) > 0); |
| } |
| |
| /** |
| * \brief Check if PHY is idle. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return 1 if PHY is idle. |
| */ |
| static inline uint8_t gmac_is_phy_idle(Gmac* p_gmac) |
| { |
| return ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) > 0); |
| } |
| |
| /** |
| * \brief Return transmit status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Transmit status. |
| */ |
| static inline uint32_t gmac_get_tx_status(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_TSR; |
| } |
| |
| /** |
| * \brief Clear transmit status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_status Transmit status. |
| */ |
| static inline void gmac_clear_tx_status(Gmac* p_gmac, uint32_t ul_status) |
| { |
| p_gmac->GMAC_TSR = ul_status; |
| } |
| |
| /** |
| * \brief Return receive status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| */ |
| static inline uint32_t gmac_get_rx_status(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_RSR; |
| } |
| |
| /** |
| * \brief Clear receive status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_status Receive status. |
| */ |
| static inline void gmac_clear_rx_status(Gmac* p_gmac, uint32_t ul_status) |
| { |
| p_gmac->GMAC_RSR = ul_status; |
| } |
| |
| /** |
| * \brief Set Rx Queue. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_addr Rx queue address. |
| */ |
| static inline void gmac_set_rx_queue(Gmac* p_gmac, uint32_t ul_addr) |
| { |
| p_gmac->GMAC_RBQB = GMAC_RBQB_ADDR_Msk & ul_addr; |
| } |
| |
| /** |
| * \brief Get Rx Queue Address. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Rx queue address. |
| */ |
| static inline uint32_t gmac_get_rx_queue(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_RBQB; |
| } |
| |
| /** |
| * \brief Set Tx Queue. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_addr Tx queue address. |
| */ |
| static inline void gmac_set_tx_queue(Gmac* p_gmac, uint32_t ul_addr) |
| { |
| p_gmac->GMAC_TBQB = GMAC_TBQB_ADDR_Msk & ul_addr; |
| } |
| |
| /** |
| * \brief Get Tx Queue. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Rx queue address. |
| */ |
| static inline uint32_t gmac_get_tx_queue(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_TBQB; |
| } |
| |
| /** |
| * \brief Enable interrupt(s). |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_source Interrupt source(s) to be enabled. |
| */ |
| static inline void gmac_enable_interrupt(Gmac* p_gmac, uint32_t ul_source) |
| { |
| p_gmac->GMAC_IER = ul_source; |
| } |
| |
| /** |
| * \brief Disable interrupt(s). |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_source Interrupt source(s) to be disabled. |
| */ |
| static inline void gmac_disable_interrupt(Gmac* p_gmac, uint32_t ul_source) |
| { |
| p_gmac->GMAC_IDR = ul_source; |
| } |
| |
| /** |
| * \brief Return interrupt status. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Interrupt status. |
| */ |
| static inline uint32_t gmac_get_interrupt_status(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_ISR; |
| } |
| |
| /** |
| * \brief Return interrupt mask. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Interrupt mask. |
| */ |
| static inline uint32_t gmac_get_interrupt_mask(Gmac* p_gmac) |
| { |
| return p_gmac->GMAC_IMR; |
| } |
| |
| /** |
| * \brief Execute PHY maintenance command. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_phy_addr PHY address. |
| * \param uc_reg_addr Register address. |
| * \param uc_rw 1 to Read, 0 to write. |
| * \param us_data Data to be performed, write only. |
| */ |
| static inline void gmac_maintain_phy(Gmac* p_gmac, |
| uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw, |
| uint16_t us_data) |
| { |
| /* Wait until bus idle */ |
| while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0); |
| /* Write maintain register */ |
| p_gmac->GMAC_MAN = GMAC_MAN_WTN(GMAC_MAN_CODE_VALUE) |
| | GMAC_MAN_CLTTO |
| | GMAC_MAN_PHYA(uc_phy_addr) |
| | GMAC_MAN_REGA(uc_reg_addr) |
| | GMAC_MAN_OP((uc_rw ? GMAC_MAN_RW_TYPE : GMAC_MAN_READ_ONLY)) |
| | GMAC_MAN_DATA(us_data); |
| } |
| |
| /** |
| * \brief Get PHY maintenance data returned. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * |
| * \return Get PHY data. |
| */ |
| static inline uint16_t gmac_get_phy_data(Gmac* p_gmac) |
| { |
| /* Wait until bus idle */ |
| while ((p_gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0); |
| /* Return data */ |
| return (uint16_t) (p_gmac->GMAC_MAN & GMAC_MAN_DATA_Msk); |
| } |
| |
| /** |
| * \brief Set Hash. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ul_hash_top Hash top. |
| * \param ul_hash_bottom Hash bottom. |
| */ |
| static inline void gmac_set_hash(Gmac* p_gmac, uint32_t ul_hash_top, |
| uint32_t ul_hash_bottom) |
| { |
| p_gmac->GMAC_HRB = ul_hash_bottom; |
| p_gmac->GMAC_HRT = ul_hash_top; |
| } |
| |
| /** |
| * \brief Set 64 bits Hash. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param ull_hash 64 bits hash value. |
| */ |
| static inline void gmac_set_hash64(Gmac* p_gmac, uint64_t ull_hash) |
| { |
| p_gmac->GMAC_HRB = (uint32_t) ull_hash; |
| p_gmac->GMAC_HRT = (uint32_t) (ull_hash >> 32); |
| } |
| |
| /** |
| * \brief Set MAC Address. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_index GMAC specific address register index. |
| * \param p_mac_addr GMAC address. |
| */ |
| static inline void gmac_set_address(Gmac* p_gmac, uint8_t uc_index, |
| uint8_t* p_mac_addr) |
| { |
| p_gmac->GMAC_SA[uc_index].GMAC_SAB = (p_mac_addr[3] << 24) |
| | (p_mac_addr[2] << 16) |
| | (p_mac_addr[1] << 8) |
| | (p_mac_addr[0]); |
| p_gmac->GMAC_SA[uc_index].GMAC_SAT = (p_mac_addr[5] << 8) |
| | (p_mac_addr[4]); |
| } |
| |
| /** |
| * \brief Set MAC Address via 2 dword. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_index GMAC specific address register index. |
| * \param ul_mac_top GMAC top address. |
| * \param ul_mac_bottom GMAC bottom address. |
| */ |
| static inline void gmac_set_address32(Gmac* p_gmac, uint8_t uc_index, |
| uint32_t ul_mac_top, uint32_t ul_mac_bottom) |
| { |
| p_gmac->GMAC_SA[uc_index].GMAC_SAB = ul_mac_bottom; |
| p_gmac->GMAC_SA[uc_index].GMAC_SAT = ul_mac_top; |
| } |
| |
| /** |
| * \brief Set MAC Address via int64. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param uc_index GMAC specific address register index. |
| * \param ull_mac 64-bit GMAC address. |
| */ |
| static inline void gmac_set_address64(Gmac* p_gmac, uint8_t uc_index, |
| uint64_t ull_mac) |
| { |
| p_gmac->GMAC_SA[uc_index].GMAC_SAB = (uint32_t) ull_mac; |
| p_gmac->GMAC_SA[uc_index].GMAC_SAT = (uint32_t) (ull_mac >> 32); |
| } |
| |
| /** |
| * \brief Select media independent interface mode. |
| * |
| * \param p_gmac Pointer to the GMAC instance. |
| * \param mode Media independent interface mode. |
| */ |
| static inline void gmac_select_mii_mode(Gmac* p_gmac, gmac_mii_mode_t mode) |
| { |
| switch (mode) { |
| case GMAC_PHY_MII: |
| case GMAC_PHY_RMII: |
| p_gmac->GMAC_UR |= GMAC_UR_RMIIMII; |
| break; |
| |
| default: |
| p_gmac->GMAC_UR &= ~GMAC_UR_RMIIMII; |
| break; |
| } |
| } |
| |
| uint8_t gmac_phy_read(Gmac* p_gmac, uint8_t uc_phy_address, uint8_t uc_address, |
| uint32_t* p_value); |
| uint8_t gmac_phy_write(Gmac* p_gmac, uint8_t uc_phy_address, |
| uint8_t uc_address, uint32_t ul_value); |
| void gmac_dev_init(Gmac* p_gmac, gmac_device_t* p_gmac_dev, |
| gmac_options_t* p_opt); |
| uint32_t gmac_dev_read(gmac_device_t* p_gmac_dev, uint8_t* p_frame, |
| uint32_t ul_frame_size, uint32_t* p_rcv_size); |
| uint32_t gmac_dev_write(gmac_device_t* p_gmac_dev, void *p_buffer, |
| uint32_t ul_size, gmac_dev_tx_cb_t func_tx_cb); |
| uint32_t gmac_dev_get_tx_load(gmac_device_t* p_gmac_dev); |
| void gmac_dev_set_rx_callback(gmac_device_t* p_gmac_dev, |
| gmac_dev_tx_cb_t func_rx_cb); |
| uint8_t gmac_dev_set_tx_wakeup_callback(gmac_device_t* p_gmac_dev, |
| gmac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold); |
| void gmac_dev_reset(gmac_device_t* p_gmac_dev); |
| void gmac_handler(gmac_device_t* p_gmac_dev); |
| |
| /// @cond 0 |
| /**INDENT-OFF**/ |
| #ifdef __cplusplus |
| } |
| #endif |
| /**INDENT-ON**/ |
| /// @endcond |
| |
| /** |
| * \page gmac_quickstart Quickstart guide for GMAC driver. |
| * |
| * This is the quickstart guide for the \ref gmac_group "Ethernet MAC", |
| * with step-by-step instructions on how to configure and use the driver in a |
| * selection of use cases. |
| * |
| * The use cases contain several code fragments. The code fragments in the |
| * steps for setup can be copied into a custom initialization function, while |
| * the steps for usage can be copied into, e.g., the main application function. |
| * |
| * \section gmac_basic_use_case Basic use case |
| * In the basic use case, the GMAC driver are configured for: |
| * - PHY component KSZ8051MNL is used |
| * - GMAC uses MII mode |
| * - The number of receive buffer is 16 |
| * - The number of transfer buffer is 8 |
| * - MAC address is set to 00-04-25-1c-a0-02 |
| * - IP address is set to 192.168.0.2 |
| * - IP address is set to 192.168.0.2 |
| * - Gateway is set to 192.168.0.1 |
| * - Network mask is 255.255.255.0 |
| * - PHY operation max retry count is 1000000 |
| * - GMAC is configured to not support copy all frame and support broadcast |
| * - The data will be read from the ethernet |
| * |
| * \section gmac_basic_use_case_setup Setup steps |
| * |
| * \subsection gmac_basic_use_case_setup_prereq Prerequisites |
| * -# \ref sysclk_group "System Clock Management (sysclock)" |
| * -# \ref pmc_group "Power Management Controller (pmc)" |
| * -# \ref ksz8051mnl_ethernet_phy_group "PHY component (KSZ8051MNL)" |
| * |
| * \subsection gmac_basic_use_case_setup_code Example code |
| * Content of conf_eth.h |
| * \code |
| * #define GMAC_RX_BUFFERS 16 |
| * #define GMAC_TX_BUFFERS 8 |
| * #define MAC_PHY_RETRY_MAX 1000000 |
| * #define ETHERNET_CONF_ETHADDR0 0x00 |
| * #define ETHERNET_CONF_ETHADDR0 0x00 |
| * #define ETHERNET_CONF_ETHADDR1 0x04 |
| * #define ETHERNET_CONF_ETHADDR2 0x25 |
| * #define ETHERNET_CONF_ETHADDR3 0x1C |
| * #define ETHERNET_CONF_ETHADDR4 0xA0 |
| * #define ETHERNET_CONF_ETHADDR5 0x02 |
| * #define ETHERNET_CONF_IPADDR0 192 |
| * #define ETHERNET_CONF_IPADDR1 168 |
| * #define ETHERNET_CONF_IPADDR2 0 |
| * #define ETHERNET_CONF_IPADDR3 2 |
| * #define ETHERNET_CONF_GATEWAY_ADDR0 192 |
| * #define ETHERNET_CONF_GATEWAY_ADDR1 168 |
| * #define ETHERNET_CONF_GATEWAY_ADDR2 0 |
| * #define ETHERNET_CONF_GATEWAY_ADDR3 1 |
| * #define ETHERNET_CONF_NET_MASK0 255 |
| * #define ETHERNET_CONF_NET_MASK1 255 |
| * #define ETHERNET_CONF_NET_MASK2 255 |
| * #define ETHERNET_CONF_NET_MASK3 0 |
| * #define ETH_PHY_MODE ETH_PHY_MODE |
| * \endcode |
| * |
| * A specific gmac device and the receive data buffer must be defined; another ul_frm_size should be defined |
| * to trace the actual size of the data received. |
| * \code |
| * static gmac_device_t gs_gmac_dev; |
| * static volatile uint8_t gs_uc_eth_buffer[GMAC_FRAME_LENTGH_MAX]; |
| * |
| * uint32_t ul_frm_size; |
| * \endcode |
| * |
| * Add to application C-file: |
| * \code |
| * void gmac_init(void) |
| * { |
| * sysclk_init(); |
| * |
| * board_init(); |
| * |
| * pmc_enable_periph_clk(ID_GMAC); |
| * |
| * gmac_option.uc_copy_all_frame = 0; |
| * gmac_option.uc_no_boardcast = 0; |
| * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); |
| * gs_gmac_dev.p_hw = GMAC; |
| * |
| * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option); |
| * |
| * NVIC_EnableIRQ(GMAC_IRQn); |
| * |
| * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz()); |
| * |
| * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR); |
| * |
| * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1); |
| * \endcode |
| * |
| * \subsection gmac_basic_use_case_setup_flow Workflow |
| * - Ensure that conf_eth.h is present and contains the |
| * following configuration symbol. This configuration file is used |
| * by the driver and should not be included by the application. |
| * -# Define the receiving buffer size used in the internal GMAC driver. |
| * The buffer size used for RX is GMAC_RX_BUFFERS * 128. |
| * If it was supposed receiving a large number of frame, the |
| * GMAC_RX_BUFFERS should be set higher. E.g., the application wants to accept |
| * a ping echo test of 2048, the GMAC_RX_BUFFERS should be set at least |
| * (2048/128)=16, and as there are additional frames coming, a preferred |
| * number is 24 depending on a normal Ethernet throughput. |
| * - \code |
| * #define GMAC_RX_BUFFERS 16 |
| * \endcode |
| * -# Define the transmitting buffer size used in the internal GMAC driver. |
| * The buffer size used for TX is GMAC_TX_BUFFERS * 1518. |
| * - \code |
| * #define GMAC_TX_BUFFERS 8 |
| * \endcode |
| * -# Define maximum retry time for a PHY read/write operation. |
| * - \code |
| * #define MAC_PHY_RETRY_MAX 1000000 |
| * \endcode |
| * -# Define the MAC address. 00:04:25:1C:A0:02 is the address reserved |
| * for ATMEL, application should always change this address to its' own. |
| * - \code |
| * #define ETHERNET_CONF_ETHADDR0 0x00 |
| * #define ETHERNET_CONF_ETHADDR1 0x04 |
| * #define ETHERNET_CONF_ETHADDR2 0x25 |
| * #define ETHERNET_CONF_ETHADDR3 0x1C |
| * #define ETHERNET_CONF_ETHADDR4 0xA0 |
| * #define ETHERNET_CONF_ETHADDR5 0x02 |
| * \endcode |
| * -# Define the IP address configration used in the application. When DHCP |
| * is enabled, this configuration is not effected. |
| * - \code |
| * #define ETHERNET_CONF_IPADDR0 192 |
| * #define ETHERNET_CONF_IPADDR1 168 |
| * #define ETHERNET_CONF_IPADDR2 0 |
| * #define ETHERNET_CONF_IPADDR3 2 |
| * #define ETHERNET_CONF_GATEWAY_ADDR0 192 |
| * #define ETHERNET_CONF_GATEWAY_ADDR1 168 |
| * #define ETHERNET_CONF_GATEWAY_ADDR2 0 |
| * #define ETHERNET_CONF_GATEWAY_ADDR3 1 |
| * #define ETHERNET_CONF_NET_MASK0 255 |
| * #define ETHERNET_CONF_NET_MASK1 255 |
| * #define ETHERNET_CONF_NET_MASK2 255 |
| * #define ETHERNET_CONF_NET_MASK3 0 |
| * \endcode |
| * -# Configure the PHY maintainance interface. |
| * - \code |
| * #define ETH_PHY_MODE GMAC_PHY_MII |
| * \endcode |
| * -# Enable the system clock: |
| * - \code sysclk_init(); \endcode |
| * -# Enable PIO configurations for GMAC: |
| * - \code board_init(); \endcode |
| * -# Enable PMC clock for GMAC: |
| * - \code pmc_enable_periph_clk(ID_GMAC); \endcode |
| * -# Set the GMAC options; it's set to copy all frame and support broadcast: |
| * - \code |
| * gmac_option.uc_copy_all_frame = 0; |
| * gmac_option.uc_no_boardcast = 0; |
| * memcpy(gmac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address)); |
| * gs_gmac_dev.p_hw = GMAC; |
| * \endcode |
| * -# Initialize GMAC device with the filled option: |
| * - \code |
| * gmac_dev_init(GMAC, &gs_gmac_dev, &gmac_option); |
| * \endcode |
| * -# Enable the interrupt service for GMAC: |
| * - \code |
| * NVIC_EnableIRQ(GMAC_IRQn); |
| * \endcode |
| * -# Initialize the PHY component: |
| * - \code |
| * ethernet_phy_init(GMAC, BOARD_GMAC_PHY_ADDR, sysclk_get_cpu_hz()); |
| * \endcode |
| * -# The link will be established based on auto negotiation. |
| * - \code |
| * ethernet_phy_auto_negotiate(GMAC, BOARD_GMAC_PHY_ADDR); |
| * \endcode |
| * -# Establish the ethernet link; the network can be worked from now on: |
| * - \code |
| * ethernet_phy_set_link(GMAC, BOARD_GMAC_PHY_ADDR, 1); |
| * \endcode |
| * |
| * \section gmac_basic_use_case_usage Usage steps |
| * \subsection gmac_basic_use_case_usage_code Example code |
| * Add to, e.g., main loop in application C-file: |
| * \code |
| * gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); |
| * \endcode |
| * |
| * \subsection gmac_basic_use_case_usage_flow Workflow |
| * -# Start reading the data from the ethernet: |
| * - \code gmac_dev_read(&gs_gmac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode |
| */ |
| |
| # define GMAC_STATS 0 |
| |
| #if( GMAC_STATS != 0 ) |
| |
| /* Here below some code to study the types and |
| frequencies of GMAC interrupts. */ |
| #define GMAC_IDX_RXUBR 0 |
| #define GMAC_IDX_TUR 1 |
| #define GMAC_IDX_RLEX 2 |
| #define GMAC_IDX_TFC 3 |
| #define GMAC_IDX_RCOMP 4 |
| #define GMAC_IDX_TCOMP 5 |
| #define GMAC_IDX_ROVR 6 |
| #define GMAC_IDX_HRESP 7 |
| #define GMAC_IDX_PFNZ 8 |
| #define GMAC_IDX_PTZ 9 |
| |
| struct SGmacStats { |
| unsigned recvCount; |
| unsigned rovrCount; |
| unsigned bnaCount; |
| unsigned sendCount; |
| unsigned sovrCount; |
| unsigned incompCount; |
| unsigned truncCount; |
| |
| unsigned intStatus[10]; |
| }; |
| extern struct SGmacStats gmacStats; |
| |
| struct SIntPair { |
| const char *name; |
| unsigned mask; |
| int index; |
| }; |
| |
| #define MK_PAIR( NAME ) #NAME, GMAC_IER_##NAME, GMAC_IDX_##NAME |
| static const struct SIntPair intPairs[] = { |
| { MK_PAIR( RXUBR ) }, /* Enable receive used bit read interrupt. */ |
| { MK_PAIR( TUR ) }, /* Enable transmit underrun interrupt. */ |
| { MK_PAIR( RLEX ) }, /* Enable retry limit exceeded interrupt. */ |
| { MK_PAIR( TFC ) }, /* Enable transmit buffers exhausted in mid-frame interrupt. */ |
| { MK_PAIR( RCOMP ) }, /* Receive complete */ |
| { MK_PAIR( TCOMP ) }, /* Enable transmit complete interrupt. */ |
| { MK_PAIR( ROVR ) }, /* Enable receive overrun interrupt. */ |
| { MK_PAIR( HRESP ) }, /* Enable Hresp not OK interrupt. */ |
| { MK_PAIR( PFNZ ) }, /* Enable pause frame received interrupt. */ |
| { MK_PAIR( PTZ ) } /* Enable pause time zero interrupt. */ |
| }; |
| |
| void gmac_show_irq_counts (); |
| |
| #endif |
| |
| #endif /* GMAC_H_INCLUDED */ |