Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-dev by
targets/TARGET_NUVOTON/TARGET_M480/device/StdDriver/m480_emac.c@172:7d866c31b3c5, 2017-08-31 (annotated)
- Committer:
- AnnaBridge
- Date:
- Thu Aug 31 17:27:04 2017 +0100
- Revision:
- 172:7d866c31b3c5
This updates the lib to the mbed lib v 150
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AnnaBridge | 172:7d866c31b3c5 | 1 | /**************************************************************************//** |
AnnaBridge | 172:7d866c31b3c5 | 2 | * @file emac.c |
AnnaBridge | 172:7d866c31b3c5 | 3 | * @version V1.00 |
AnnaBridge | 172:7d866c31b3c5 | 4 | * @brief M480 EMAC driver source file |
AnnaBridge | 172:7d866c31b3c5 | 5 | * |
AnnaBridge | 172:7d866c31b3c5 | 6 | * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. |
AnnaBridge | 172:7d866c31b3c5 | 7 | *****************************************************************************/ |
AnnaBridge | 172:7d866c31b3c5 | 8 | #include <stdio.h> |
AnnaBridge | 172:7d866c31b3c5 | 9 | #include <string.h> |
AnnaBridge | 172:7d866c31b3c5 | 10 | #include "M480.h" |
AnnaBridge | 172:7d866c31b3c5 | 11 | |
AnnaBridge | 172:7d866c31b3c5 | 12 | |
AnnaBridge | 172:7d866c31b3c5 | 13 | /** @addtogroup M480_Device_Driver M480 Device Driver |
AnnaBridge | 172:7d866c31b3c5 | 14 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 15 | */ |
AnnaBridge | 172:7d866c31b3c5 | 16 | |
AnnaBridge | 172:7d866c31b3c5 | 17 | /** @addtogroup M480_EMAC_Driver EMAC Driver |
AnnaBridge | 172:7d866c31b3c5 | 18 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 19 | */ |
AnnaBridge | 172:7d866c31b3c5 | 20 | |
AnnaBridge | 172:7d866c31b3c5 | 21 | |
AnnaBridge | 172:7d866c31b3c5 | 22 | /* Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */ |
AnnaBridge | 172:7d866c31b3c5 | 23 | /** @cond HIDDEN_SYMBOLS */ |
AnnaBridge | 172:7d866c31b3c5 | 24 | |
AnnaBridge | 172:7d866c31b3c5 | 25 | /** @addtogroup M480_EMAC_EXPORTED_CONSTANTS EMAC Exported Constants |
AnnaBridge | 172:7d866c31b3c5 | 26 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 27 | */ |
AnnaBridge | 172:7d866c31b3c5 | 28 | |
AnnaBridge | 172:7d866c31b3c5 | 29 | /* PHY Register Description */ |
AnnaBridge | 172:7d866c31b3c5 | 30 | #define PHY_CNTL_REG 0x00UL /*!< PHY control register address */ |
AnnaBridge | 172:7d866c31b3c5 | 31 | #define PHY_STATUS_REG 0x01UL /*!< PHY status register address */ |
AnnaBridge | 172:7d866c31b3c5 | 32 | #define PHY_ID1_REG 0x02UL /*!< PHY ID1 register */ |
AnnaBridge | 172:7d866c31b3c5 | 33 | #define PHY_ID2_REG 0x03UL /*!< PHY ID2 register */ |
AnnaBridge | 172:7d866c31b3c5 | 34 | #define PHY_ANA_REG 0x04UL /*!< PHY auto-negotiation advertisement register */ |
AnnaBridge | 172:7d866c31b3c5 | 35 | #define PHY_ANLPA_REG 0x05UL /*!< PHY auto-negotiation link partner availability register */ |
AnnaBridge | 172:7d866c31b3c5 | 36 | #define PHY_ANE_REG 0x06UL /*!< PHY auto-negotiation expansion register */ |
AnnaBridge | 172:7d866c31b3c5 | 37 | |
AnnaBridge | 172:7d866c31b3c5 | 38 | /* PHY Control Register */ |
AnnaBridge | 172:7d866c31b3c5 | 39 | #define PHY_CNTL_RESET_PHY (1UL << 15UL) |
AnnaBridge | 172:7d866c31b3c5 | 40 | #define PHY_CNTL_DR_100MB (1UL << 13UL) |
AnnaBridge | 172:7d866c31b3c5 | 41 | #define PHY_CNTL_ENABLE_AN (1UL << 12UL) |
AnnaBridge | 172:7d866c31b3c5 | 42 | #define PHY_CNTL_POWER_DOWN (1UL << 11UL) |
AnnaBridge | 172:7d866c31b3c5 | 43 | #define PHY_CNTL_RESTART_AN (1UL << 9UL) |
AnnaBridge | 172:7d866c31b3c5 | 44 | #define PHY_CNTL_FULLDUPLEX (1UL << 8UL) |
AnnaBridge | 172:7d866c31b3c5 | 45 | |
AnnaBridge | 172:7d866c31b3c5 | 46 | /* PHY Status Register */ |
AnnaBridge | 172:7d866c31b3c5 | 47 | #define PHY_STATUS_AN_COMPLETE (1UL << 5UL) |
AnnaBridge | 172:7d866c31b3c5 | 48 | #define PHY_STATUS_LINK_VALID (1UL << 2UL) |
AnnaBridge | 172:7d866c31b3c5 | 49 | |
AnnaBridge | 172:7d866c31b3c5 | 50 | /* PHY Auto-negotiation Advertisement Register */ |
AnnaBridge | 172:7d866c31b3c5 | 51 | #define PHY_ANA_DR100_TX_FULL (1UL << 8UL) |
AnnaBridge | 172:7d866c31b3c5 | 52 | #define PHY_ANA_DR100_TX_HALF (1UL << 7UL) |
AnnaBridge | 172:7d866c31b3c5 | 53 | #define PHY_ANA_DR10_TX_FULL (1UL << 6UL) |
AnnaBridge | 172:7d866c31b3c5 | 54 | #define PHY_ANA_DR10_TX_HALF (1UL << 5UL) |
AnnaBridge | 172:7d866c31b3c5 | 55 | #define PHY_ANA_IEEE_802_3_CSMA_CD (1UL << 0UL) |
AnnaBridge | 172:7d866c31b3c5 | 56 | |
AnnaBridge | 172:7d866c31b3c5 | 57 | /* PHY Auto-negotiation Link Partner Advertisement Register */ |
AnnaBridge | 172:7d866c31b3c5 | 58 | #define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL) |
AnnaBridge | 172:7d866c31b3c5 | 59 | #define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL) |
AnnaBridge | 172:7d866c31b3c5 | 60 | #define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL) |
AnnaBridge | 172:7d866c31b3c5 | 61 | #define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL) |
AnnaBridge | 172:7d866c31b3c5 | 62 | |
AnnaBridge | 172:7d866c31b3c5 | 63 | /* EMAC Tx/Rx descriptor's owner bit */ |
AnnaBridge | 172:7d866c31b3c5 | 64 | #define EMAC_DESC_OWN_EMAC 0x80000000UL /*!< Set owner to EMAC */ |
AnnaBridge | 172:7d866c31b3c5 | 65 | #define EMAC_DESC_OWN_CPU 0x00000000UL /*!< Set owner to CPU */ |
AnnaBridge | 172:7d866c31b3c5 | 66 | |
AnnaBridge | 172:7d866c31b3c5 | 67 | /* Rx Frame Descriptor Status */ |
AnnaBridge | 172:7d866c31b3c5 | 68 | #define EMAC_RXFD_RTSAS 0x0080UL /*!< Time Stamp Available */ |
AnnaBridge | 172:7d866c31b3c5 | 69 | #define EMAC_RXFD_RP 0x0040UL /*!< Runt Packet */ |
AnnaBridge | 172:7d866c31b3c5 | 70 | #define EMAC_RXFD_ALIE 0x0020UL /*!< Alignment Error */ |
AnnaBridge | 172:7d866c31b3c5 | 71 | #define EMAC_RXFD_RXGD 0x0010UL /*!< Receiving Good packet received */ |
AnnaBridge | 172:7d866c31b3c5 | 72 | #define EMAC_RXFD_PTLE 0x0008UL /*!< Packet Too Long Error */ |
AnnaBridge | 172:7d866c31b3c5 | 73 | #define EMAC_RXFD_CRCE 0x0002UL /*!< CRC Error */ |
AnnaBridge | 172:7d866c31b3c5 | 74 | #define EMAC_RXFD_RXINTR 0x0001UL /*!< Interrupt on receive */ |
AnnaBridge | 172:7d866c31b3c5 | 75 | |
AnnaBridge | 172:7d866c31b3c5 | 76 | /* Tx Frame Descriptor's Control bits */ |
AnnaBridge | 172:7d866c31b3c5 | 77 | #define EMAC_TXFD_TTSEN 0x08UL /*!< Tx time stamp enable */ |
AnnaBridge | 172:7d866c31b3c5 | 78 | #define EMAC_TXFD_INTEN 0x04UL /*!< Tx interrupt enable */ |
AnnaBridge | 172:7d866c31b3c5 | 79 | #define EMAC_TXFD_CRCAPP 0x02UL /*!< Append CRC */ |
AnnaBridge | 172:7d866c31b3c5 | 80 | #define EMAC_TXFD_PADEN 0x01UL /*!< Padding mode enable */ |
AnnaBridge | 172:7d866c31b3c5 | 81 | |
AnnaBridge | 172:7d866c31b3c5 | 82 | /* Tx Frame Descriptor Status */ |
AnnaBridge | 172:7d866c31b3c5 | 83 | #define EMAC_TXFD_TXINTR 0x0001UL /*!< Interrupt on Transmit */ |
AnnaBridge | 172:7d866c31b3c5 | 84 | #define EMAC_TXFD_DEF 0x0002UL /*!< Transmit deferred */ |
AnnaBridge | 172:7d866c31b3c5 | 85 | #define EMAC_TXFD_TXCP 0x0008UL /*!< Transmission Completion */ |
AnnaBridge | 172:7d866c31b3c5 | 86 | #define EMAC_TXFD_EXDEF 0x0010UL /*!< Exceed Deferral */ |
AnnaBridge | 172:7d866c31b3c5 | 87 | #define EMAC_TXFD_NCS 0x0020UL /*!< No Carrier Sense Error */ |
AnnaBridge | 172:7d866c31b3c5 | 88 | #define EMAC_TXFD_TXABT 0x0040UL /*!< Transmission Abort */ |
AnnaBridge | 172:7d866c31b3c5 | 89 | #define EMAC_TXFD_LC 0x0080UL /*!< Late Collision */ |
AnnaBridge | 172:7d866c31b3c5 | 90 | #define EMAC_TXFD_TXHA 0x0100UL /*!< Transmission halted */ |
AnnaBridge | 172:7d866c31b3c5 | 91 | #define EMAC_TXFD_PAU 0x0200UL /*!< Paused */ |
AnnaBridge | 172:7d866c31b3c5 | 92 | #define EMAC_TXFD_SQE 0x0400UL /*!< SQE error */ |
AnnaBridge | 172:7d866c31b3c5 | 93 | #define EMAC_TXFD_TTSAS 0x0800UL /*!< Time Stamp available */ |
AnnaBridge | 172:7d866c31b3c5 | 94 | |
AnnaBridge | 172:7d866c31b3c5 | 95 | /*@}*/ /* end of group M480_EMAC_EXPORTED_CONSTANTS */ |
AnnaBridge | 172:7d866c31b3c5 | 96 | |
AnnaBridge | 172:7d866c31b3c5 | 97 | /** @addtogroup M480_EMAC_EXPORTED_TYPEDEF EMAC Exported Type Defines |
AnnaBridge | 172:7d866c31b3c5 | 98 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 99 | */ |
AnnaBridge | 172:7d866c31b3c5 | 100 | |
AnnaBridge | 172:7d866c31b3c5 | 101 | /** Tx/Rx buffer descriptor structure */ |
AnnaBridge | 172:7d866c31b3c5 | 102 | typedef struct { |
AnnaBridge | 172:7d866c31b3c5 | 103 | uint32_t u32Status1; /*!< Status word 1 */ |
AnnaBridge | 172:7d866c31b3c5 | 104 | uint32_t u32Data; /*!< Pointer to data buffer */ |
AnnaBridge | 172:7d866c31b3c5 | 105 | uint32_t u32Status2; /*!< Status word 2 */ |
AnnaBridge | 172:7d866c31b3c5 | 106 | uint32_t u32Next; /*!< Pointer to next descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 107 | uint32_t u32Backup1; /*!< For backup descriptor fields over written by time stamp */ |
AnnaBridge | 172:7d866c31b3c5 | 108 | uint32_t u32Backup2; /*!< For backup descriptor fields over written by time stamp */ |
AnnaBridge | 172:7d866c31b3c5 | 109 | } EMAC_DESCRIPTOR_T; |
AnnaBridge | 172:7d866c31b3c5 | 110 | |
AnnaBridge | 172:7d866c31b3c5 | 111 | /** Tx/Rx buffer structure */ |
AnnaBridge | 172:7d866c31b3c5 | 112 | typedef struct { |
AnnaBridge | 172:7d866c31b3c5 | 113 | uint8_t au8Buf[1520]; |
AnnaBridge | 172:7d866c31b3c5 | 114 | } EMAC_FRAME_T; |
AnnaBridge | 172:7d866c31b3c5 | 115 | |
AnnaBridge | 172:7d866c31b3c5 | 116 | /*@}*/ /* end of group M480_EMAC_EXPORTED_TYPEDEF */ |
AnnaBridge | 172:7d866c31b3c5 | 117 | |
AnnaBridge | 172:7d866c31b3c5 | 118 | /* local variables */ |
AnnaBridge | 172:7d866c31b3c5 | 119 | static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 120 | static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 121 | static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 122 | static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 123 | |
AnnaBridge | 172:7d866c31b3c5 | 124 | |
AnnaBridge | 172:7d866c31b3c5 | 125 | static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 126 | static uint32_t s_u32EnableTs = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 127 | |
AnnaBridge | 172:7d866c31b3c5 | 128 | static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data); |
AnnaBridge | 172:7d866c31b3c5 | 129 | static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr); |
AnnaBridge | 172:7d866c31b3c5 | 130 | static void EMAC_PhyInit(void); |
AnnaBridge | 172:7d866c31b3c5 | 131 | static void EMAC_TxDescInit(void); |
AnnaBridge | 172:7d866c31b3c5 | 132 | static void EMAC_RxDescInit(void); |
AnnaBridge | 172:7d866c31b3c5 | 133 | static uint32_t EMAC_Subsec2Nsec(uint32_t subsec); |
AnnaBridge | 172:7d866c31b3c5 | 134 | static uint32_t EMAC_Nsec2Subsec(uint32_t nsec); |
AnnaBridge | 172:7d866c31b3c5 | 135 | |
AnnaBridge | 172:7d866c31b3c5 | 136 | /** @addtogroup M480_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions |
AnnaBridge | 172:7d866c31b3c5 | 137 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 138 | */ |
AnnaBridge | 172:7d866c31b3c5 | 139 | |
AnnaBridge | 172:7d866c31b3c5 | 140 | /** |
AnnaBridge | 172:7d866c31b3c5 | 141 | * @brief Trigger EMAC Rx function |
AnnaBridge | 172:7d866c31b3c5 | 142 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 143 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 144 | */ |
AnnaBridge | 172:7d866c31b3c5 | 145 | #define EMAC_TRIGGER_RX() do{EMAC->RXST = 0UL;}while(0) |
AnnaBridge | 172:7d866c31b3c5 | 146 | |
AnnaBridge | 172:7d866c31b3c5 | 147 | /** |
AnnaBridge | 172:7d866c31b3c5 | 148 | * @brief Trigger EMAC Tx function |
AnnaBridge | 172:7d866c31b3c5 | 149 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 150 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 151 | */ |
AnnaBridge | 172:7d866c31b3c5 | 152 | #define EMAC_TRIGGER_TX() do{EMAC->TXST = 0UL;}while(0) |
AnnaBridge | 172:7d866c31b3c5 | 153 | |
AnnaBridge | 172:7d866c31b3c5 | 154 | |
AnnaBridge | 172:7d866c31b3c5 | 155 | /** |
AnnaBridge | 172:7d866c31b3c5 | 156 | * @brief Write PHY register |
AnnaBridge | 172:7d866c31b3c5 | 157 | * @param[in] u32Reg PHY register number |
AnnaBridge | 172:7d866c31b3c5 | 158 | * @param[in] u32Addr PHY address, this address is board dependent |
AnnaBridge | 172:7d866c31b3c5 | 159 | * @param[in] u32Data data to write to PHY register |
AnnaBridge | 172:7d866c31b3c5 | 160 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 161 | */ |
AnnaBridge | 172:7d866c31b3c5 | 162 | static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data) |
AnnaBridge | 172:7d866c31b3c5 | 163 | { |
AnnaBridge | 172:7d866c31b3c5 | 164 | /* Set data register */ |
AnnaBridge | 172:7d866c31b3c5 | 165 | EMAC->MIIMDAT = u32Data ; |
AnnaBridge | 172:7d866c31b3c5 | 166 | /* Set PHY address, PHY register address, busy bit and write bit */ |
AnnaBridge | 172:7d866c31b3c5 | 167 | EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 168 | /* Wait write complete by polling busy bit. */ |
AnnaBridge | 172:7d866c31b3c5 | 169 | while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 170 | ; |
AnnaBridge | 172:7d866c31b3c5 | 171 | } |
AnnaBridge | 172:7d866c31b3c5 | 172 | |
AnnaBridge | 172:7d866c31b3c5 | 173 | } |
AnnaBridge | 172:7d866c31b3c5 | 174 | |
AnnaBridge | 172:7d866c31b3c5 | 175 | /** |
AnnaBridge | 172:7d866c31b3c5 | 176 | * @brief Read PHY register |
AnnaBridge | 172:7d866c31b3c5 | 177 | * @param[in] u32Reg PHY register number |
AnnaBridge | 172:7d866c31b3c5 | 178 | * @param[in] u32Addr PHY address, this address is board dependent |
AnnaBridge | 172:7d866c31b3c5 | 179 | * @return Value read from PHY register |
AnnaBridge | 172:7d866c31b3c5 | 180 | */ |
AnnaBridge | 172:7d866c31b3c5 | 181 | static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr) |
AnnaBridge | 172:7d866c31b3c5 | 182 | { |
AnnaBridge | 172:7d866c31b3c5 | 183 | /* Set PHY address, PHY register address, busy bit */ |
AnnaBridge | 172:7d866c31b3c5 | 184 | EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 185 | /* Wait read complete by polling busy bit */ |
AnnaBridge | 172:7d866c31b3c5 | 186 | while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 187 | ; |
AnnaBridge | 172:7d866c31b3c5 | 188 | } |
AnnaBridge | 172:7d866c31b3c5 | 189 | /* Get return data */ |
AnnaBridge | 172:7d866c31b3c5 | 190 | return EMAC->MIIMDAT; |
AnnaBridge | 172:7d866c31b3c5 | 191 | } |
AnnaBridge | 172:7d866c31b3c5 | 192 | |
AnnaBridge | 172:7d866c31b3c5 | 193 | /** |
AnnaBridge | 172:7d866c31b3c5 | 194 | * @brief Initialize PHY chip, check for the auto-negotiation result. |
AnnaBridge | 172:7d866c31b3c5 | 195 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 196 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 197 | */ |
AnnaBridge | 172:7d866c31b3c5 | 198 | static void EMAC_PhyInit(void) |
AnnaBridge | 172:7d866c31b3c5 | 199 | { |
AnnaBridge | 172:7d866c31b3c5 | 200 | uint32_t reg; |
AnnaBridge | 172:7d866c31b3c5 | 201 | uint32_t i = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 202 | |
AnnaBridge | 172:7d866c31b3c5 | 203 | /* Reset Phy Chip */ |
AnnaBridge | 172:7d866c31b3c5 | 204 | EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY); |
AnnaBridge | 172:7d866c31b3c5 | 205 | |
AnnaBridge | 172:7d866c31b3c5 | 206 | /* Wait until reset complete */ |
AnnaBridge | 172:7d866c31b3c5 | 207 | while (1) { |
AnnaBridge | 172:7d866c31b3c5 | 208 | reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ; |
AnnaBridge | 172:7d866c31b3c5 | 209 | if ((reg & PHY_CNTL_RESET_PHY)==0UL) { |
AnnaBridge | 172:7d866c31b3c5 | 210 | break; |
AnnaBridge | 172:7d866c31b3c5 | 211 | } |
AnnaBridge | 172:7d866c31b3c5 | 212 | } |
AnnaBridge | 172:7d866c31b3c5 | 213 | while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) { |
AnnaBridge | 172:7d866c31b3c5 | 214 | if(i++ > 80000UL) { /* Cable not connected */ |
AnnaBridge | 172:7d866c31b3c5 | 215 | EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 216 | EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 217 | break; |
AnnaBridge | 172:7d866c31b3c5 | 218 | } |
AnnaBridge | 172:7d866c31b3c5 | 219 | } |
AnnaBridge | 172:7d866c31b3c5 | 220 | |
AnnaBridge | 172:7d866c31b3c5 | 221 | if(i <= 80000UL) { |
AnnaBridge | 172:7d866c31b3c5 | 222 | /* Configure auto negotiation capability */ |
AnnaBridge | 172:7d866c31b3c5 | 223 | EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL | |
AnnaBridge | 172:7d866c31b3c5 | 224 | PHY_ANA_DR100_TX_HALF | |
AnnaBridge | 172:7d866c31b3c5 | 225 | PHY_ANA_DR10_TX_FULL | |
AnnaBridge | 172:7d866c31b3c5 | 226 | PHY_ANA_DR10_TX_HALF | |
AnnaBridge | 172:7d866c31b3c5 | 227 | PHY_ANA_IEEE_802_3_CSMA_CD); |
AnnaBridge | 172:7d866c31b3c5 | 228 | /* Restart auto negotiation */ |
AnnaBridge | 172:7d866c31b3c5 | 229 | EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN); |
AnnaBridge | 172:7d866c31b3c5 | 230 | |
AnnaBridge | 172:7d866c31b3c5 | 231 | /* Wait for auto-negotiation complete */ |
AnnaBridge | 172:7d866c31b3c5 | 232 | while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE)) { |
AnnaBridge | 172:7d866c31b3c5 | 233 | ; |
AnnaBridge | 172:7d866c31b3c5 | 234 | } |
AnnaBridge | 172:7d866c31b3c5 | 235 | /* Check link valid again. Some PHYs needs to check result after link valid bit set */ |
AnnaBridge | 172:7d866c31b3c5 | 236 | while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)) { |
AnnaBridge | 172:7d866c31b3c5 | 237 | ; |
AnnaBridge | 172:7d866c31b3c5 | 238 | } |
AnnaBridge | 172:7d866c31b3c5 | 239 | |
AnnaBridge | 172:7d866c31b3c5 | 240 | /* Check link partner capability */ |
AnnaBridge | 172:7d866c31b3c5 | 241 | reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ; |
AnnaBridge | 172:7d866c31b3c5 | 242 | if (reg & PHY_ANLPA_DR100_TX_FULL) { |
AnnaBridge | 172:7d866c31b3c5 | 243 | EMAC->CTL |= EMAC_CTL_OPMODE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 244 | EMAC->CTL |= EMAC_CTL_FUDUP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 245 | } else if (reg & PHY_ANLPA_DR100_TX_HALF) { |
AnnaBridge | 172:7d866c31b3c5 | 246 | EMAC->CTL |= EMAC_CTL_OPMODE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 247 | EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 248 | } else if (reg & PHY_ANLPA_DR10_TX_FULL) { |
AnnaBridge | 172:7d866c31b3c5 | 249 | EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 250 | EMAC->CTL |= EMAC_CTL_FUDUP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 251 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 252 | EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 253 | EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 254 | } |
AnnaBridge | 172:7d866c31b3c5 | 255 | } |
AnnaBridge | 172:7d866c31b3c5 | 256 | } |
AnnaBridge | 172:7d866c31b3c5 | 257 | |
AnnaBridge | 172:7d866c31b3c5 | 258 | /** |
AnnaBridge | 172:7d866c31b3c5 | 259 | * @brief Initial EMAC Tx descriptors and get Tx descriptor base address |
AnnaBridge | 172:7d866c31b3c5 | 260 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 261 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 262 | */ |
AnnaBridge | 172:7d866c31b3c5 | 263 | static void EMAC_TxDescInit(void) |
AnnaBridge | 172:7d866c31b3c5 | 264 | { |
AnnaBridge | 172:7d866c31b3c5 | 265 | uint32_t i; |
AnnaBridge | 172:7d866c31b3c5 | 266 | |
AnnaBridge | 172:7d866c31b3c5 | 267 | /* Get Frame descriptor's base address. */ |
AnnaBridge | 172:7d866c31b3c5 | 268 | EMAC->TXDSA = (uint32_t)&tx_desc[0]; |
AnnaBridge | 172:7d866c31b3c5 | 269 | u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0]; |
AnnaBridge | 172:7d866c31b3c5 | 270 | |
AnnaBridge | 172:7d866c31b3c5 | 271 | for(i = 0UL; i < EMAC_TX_DESC_SIZE; i++) { |
AnnaBridge | 172:7d866c31b3c5 | 272 | |
AnnaBridge | 172:7d866c31b3c5 | 273 | if(s_u32EnableTs) { |
AnnaBridge | 172:7d866c31b3c5 | 274 | tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN; |
AnnaBridge | 172:7d866c31b3c5 | 275 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 276 | tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN; |
AnnaBridge | 172:7d866c31b3c5 | 277 | } |
AnnaBridge | 172:7d866c31b3c5 | 278 | tx_desc[i].u32Data = (uint32_t)((uint32_t)&tx_buf[i]); |
AnnaBridge | 172:7d866c31b3c5 | 279 | tx_desc[i].u32Backup1 = tx_desc[i].u32Data; |
AnnaBridge | 172:7d866c31b3c5 | 280 | tx_desc[i].u32Status2 = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 281 | tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1UL) % EMAC_TX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 282 | tx_desc[i].u32Backup2 = tx_desc[i].u32Next; |
AnnaBridge | 172:7d866c31b3c5 | 283 | |
AnnaBridge | 172:7d866c31b3c5 | 284 | } |
AnnaBridge | 172:7d866c31b3c5 | 285 | |
AnnaBridge | 172:7d866c31b3c5 | 286 | } |
AnnaBridge | 172:7d866c31b3c5 | 287 | |
AnnaBridge | 172:7d866c31b3c5 | 288 | |
AnnaBridge | 172:7d866c31b3c5 | 289 | /** |
AnnaBridge | 172:7d866c31b3c5 | 290 | * @brief Initial EMAC Rx descriptors and get Rx descriptor base address |
AnnaBridge | 172:7d866c31b3c5 | 291 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 292 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 293 | */ |
AnnaBridge | 172:7d866c31b3c5 | 294 | static void EMAC_RxDescInit(void) |
AnnaBridge | 172:7d866c31b3c5 | 295 | { |
AnnaBridge | 172:7d866c31b3c5 | 296 | |
AnnaBridge | 172:7d866c31b3c5 | 297 | uint32_t i; |
AnnaBridge | 172:7d866c31b3c5 | 298 | |
AnnaBridge | 172:7d866c31b3c5 | 299 | /* Get Frame descriptor's base address. */ |
AnnaBridge | 172:7d866c31b3c5 | 300 | EMAC->RXDSA = (uint32_t)&rx_desc[0]; |
AnnaBridge | 172:7d866c31b3c5 | 301 | u32CurrentRxDesc = (uint32_t)&rx_desc[0]; |
AnnaBridge | 172:7d866c31b3c5 | 302 | |
AnnaBridge | 172:7d866c31b3c5 | 303 | for(i = 0UL; i < EMAC_RX_DESC_SIZE; i++) { |
AnnaBridge | 172:7d866c31b3c5 | 304 | rx_desc[i].u32Status1 = EMAC_DESC_OWN_EMAC; |
AnnaBridge | 172:7d866c31b3c5 | 305 | rx_desc[i].u32Data = (uint32_t)((uint32_t)&rx_buf[i]); |
AnnaBridge | 172:7d866c31b3c5 | 306 | rx_desc[i].u32Backup1 = rx_desc[i].u32Data; |
AnnaBridge | 172:7d866c31b3c5 | 307 | rx_desc[i].u32Status2 = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 308 | rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1UL) % EMAC_RX_DESC_SIZE]; |
AnnaBridge | 172:7d866c31b3c5 | 309 | rx_desc[i].u32Backup2 = rx_desc[i].u32Next; |
AnnaBridge | 172:7d866c31b3c5 | 310 | } |
AnnaBridge | 172:7d866c31b3c5 | 311 | |
AnnaBridge | 172:7d866c31b3c5 | 312 | } |
AnnaBridge | 172:7d866c31b3c5 | 313 | |
AnnaBridge | 172:7d866c31b3c5 | 314 | /** |
AnnaBridge | 172:7d866c31b3c5 | 315 | * @brief Convert subsecond value to nano second |
AnnaBridge | 172:7d866c31b3c5 | 316 | * @param[in] subsec Subsecond value to be convert |
AnnaBridge | 172:7d866c31b3c5 | 317 | * @return Nano second |
AnnaBridge | 172:7d866c31b3c5 | 318 | */ |
AnnaBridge | 172:7d866c31b3c5 | 319 | static uint32_t EMAC_Subsec2Nsec(uint32_t subsec) |
AnnaBridge | 172:7d866c31b3c5 | 320 | { |
AnnaBridge | 172:7d866c31b3c5 | 321 | /* 2^31 subsec == 10^9 ns */ |
AnnaBridge | 172:7d866c31b3c5 | 322 | uint64_t i; |
AnnaBridge | 172:7d866c31b3c5 | 323 | i = 1000000000ull * (uint64_t)subsec; |
AnnaBridge | 172:7d866c31b3c5 | 324 | i >>= 31; |
AnnaBridge | 172:7d866c31b3c5 | 325 | return((uint32_t)i); |
AnnaBridge | 172:7d866c31b3c5 | 326 | } |
AnnaBridge | 172:7d866c31b3c5 | 327 | |
AnnaBridge | 172:7d866c31b3c5 | 328 | /** |
AnnaBridge | 172:7d866c31b3c5 | 329 | * @brief Convert nano second to subsecond value |
AnnaBridge | 172:7d866c31b3c5 | 330 | * @param[in] nsec Nano second to be convert |
AnnaBridge | 172:7d866c31b3c5 | 331 | * @return Subsecond |
AnnaBridge | 172:7d866c31b3c5 | 332 | */ |
AnnaBridge | 172:7d866c31b3c5 | 333 | static uint32_t EMAC_Nsec2Subsec(uint32_t nsec) |
AnnaBridge | 172:7d866c31b3c5 | 334 | { |
AnnaBridge | 172:7d866c31b3c5 | 335 | /* 10^9 ns = 2^31 subsec */ |
AnnaBridge | 172:7d866c31b3c5 | 336 | uint64_t i; |
AnnaBridge | 172:7d866c31b3c5 | 337 | i = (1ull << 31) * nsec; |
AnnaBridge | 172:7d866c31b3c5 | 338 | i /= 1000000000ull; |
AnnaBridge | 172:7d866c31b3c5 | 339 | return((uint32_t)i); |
AnnaBridge | 172:7d866c31b3c5 | 340 | } |
AnnaBridge | 172:7d866c31b3c5 | 341 | |
AnnaBridge | 172:7d866c31b3c5 | 342 | |
AnnaBridge | 172:7d866c31b3c5 | 343 | /*@}*/ /* end of group M480_EMAC_EXPORTED_FUNCTIONS */ |
AnnaBridge | 172:7d866c31b3c5 | 344 | |
AnnaBridge | 172:7d866c31b3c5 | 345 | |
AnnaBridge | 172:7d866c31b3c5 | 346 | |
AnnaBridge | 172:7d866c31b3c5 | 347 | /** @endcond HIDDEN_SYMBOLS */ |
AnnaBridge | 172:7d866c31b3c5 | 348 | |
AnnaBridge | 172:7d866c31b3c5 | 349 | |
AnnaBridge | 172:7d866c31b3c5 | 350 | /** @addtogroup M480_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions |
AnnaBridge | 172:7d866c31b3c5 | 351 | @{ |
AnnaBridge | 172:7d866c31b3c5 | 352 | */ |
AnnaBridge | 172:7d866c31b3c5 | 353 | |
AnnaBridge | 172:7d866c31b3c5 | 354 | |
AnnaBridge | 172:7d866c31b3c5 | 355 | /** |
AnnaBridge | 172:7d866c31b3c5 | 356 | * @brief Initialize EMAC interface, including descriptors, MAC address, and PHY. |
AnnaBridge | 172:7d866c31b3c5 | 357 | * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address |
AnnaBridge | 172:7d866c31b3c5 | 358 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 359 | * @note This API sets EMAC to work in RMII mode, but could configure to MII mode later with \ref EMAC_ENABLE_MII_INTF macro |
AnnaBridge | 172:7d866c31b3c5 | 360 | * @note This API configures EMAC to receive all broadcast and multicast packets, but could configure to other settings with |
AnnaBridge | 172:7d866c31b3c5 | 361 | * \ref EMAC_ENABLE_RECV_BCASTPKT, \ref EMAC_DISABLE_RECV_BCASTPKT, \ref EMAC_ENABLE_RECV_MCASTPKT, and \ref EMAC_DISABLE_RECV_MCASTPKT |
AnnaBridge | 172:7d866c31b3c5 | 362 | * @note Receive(RX) and transmit(TX) are not enabled yet, application must call \ref EMAC_ENABLE_RX and \ref EMAC_ENABLE_TX to |
AnnaBridge | 172:7d866c31b3c5 | 363 | * enable receive and transmit function. |
AnnaBridge | 172:7d866c31b3c5 | 364 | */ |
AnnaBridge | 172:7d866c31b3c5 | 365 | void EMAC_Open(uint8_t *pu8MacAddr) |
AnnaBridge | 172:7d866c31b3c5 | 366 | { |
AnnaBridge | 172:7d866c31b3c5 | 367 | /* Enable transmit and receive descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 368 | EMAC_TxDescInit(); |
AnnaBridge | 172:7d866c31b3c5 | 369 | EMAC_RxDescInit(); |
AnnaBridge | 172:7d866c31b3c5 | 370 | |
AnnaBridge | 172:7d866c31b3c5 | 371 | /* Set the CAM Control register and the MAC address value */ |
AnnaBridge | 172:7d866c31b3c5 | 372 | EMAC_SetMacAddr(pu8MacAddr); |
AnnaBridge | 172:7d866c31b3c5 | 373 | |
AnnaBridge | 172:7d866c31b3c5 | 374 | /* Configure the MAC interrupt enable register. */ |
AnnaBridge | 172:7d866c31b3c5 | 375 | EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 376 | EMAC_INTEN_TXIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 377 | EMAC_INTEN_RXGDIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 378 | EMAC_INTEN_TXCPIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 379 | EMAC_INTEN_RXBEIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 380 | EMAC_INTEN_TXBEIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 381 | EMAC_INTEN_RDUIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 382 | EMAC_INTEN_TSALMIEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 383 | EMAC_INTEN_WOLIEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 384 | |
AnnaBridge | 172:7d866c31b3c5 | 385 | /* Configure the MAC control register. */ |
AnnaBridge | 172:7d866c31b3c5 | 386 | EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 387 | EMAC_CTL_RMIIEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 388 | |
AnnaBridge | 172:7d866c31b3c5 | 389 | /* Accept packets for us and all broadcast and multicast packets */ |
AnnaBridge | 172:7d866c31b3c5 | 390 | EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 391 | EMAC_CAMCTL_AMP_Msk | |
AnnaBridge | 172:7d866c31b3c5 | 392 | EMAC_CAMCTL_ABP_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 393 | |
AnnaBridge | 172:7d866c31b3c5 | 394 | EMAC_PhyInit(); |
AnnaBridge | 172:7d866c31b3c5 | 395 | } |
AnnaBridge | 172:7d866c31b3c5 | 396 | |
AnnaBridge | 172:7d866c31b3c5 | 397 | /** |
AnnaBridge | 172:7d866c31b3c5 | 398 | * @brief This function stop all receive and transmit activity and disable MAC interface |
AnnaBridge | 172:7d866c31b3c5 | 399 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 400 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 401 | */ |
AnnaBridge | 172:7d866c31b3c5 | 402 | |
AnnaBridge | 172:7d866c31b3c5 | 403 | void EMAC_Close(void) |
AnnaBridge | 172:7d866c31b3c5 | 404 | { |
AnnaBridge | 172:7d866c31b3c5 | 405 | EMAC->CTL |= EMAC_CTL_RST_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 406 | while(EMAC->CTL & EMAC_CTL_RST_Msk) {} |
AnnaBridge | 172:7d866c31b3c5 | 407 | } |
AnnaBridge | 172:7d866c31b3c5 | 408 | |
AnnaBridge | 172:7d866c31b3c5 | 409 | /** |
AnnaBridge | 172:7d866c31b3c5 | 410 | * @brief Set the device MAC address |
AnnaBridge | 172:7d866c31b3c5 | 411 | * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address |
AnnaBridge | 172:7d866c31b3c5 | 412 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 413 | */ |
AnnaBridge | 172:7d866c31b3c5 | 414 | void EMAC_SetMacAddr(uint8_t *pu8MacAddr) |
AnnaBridge | 172:7d866c31b3c5 | 415 | { |
AnnaBridge | 172:7d866c31b3c5 | 416 | EMAC_EnableCamEntry(0UL, pu8MacAddr); |
AnnaBridge | 172:7d866c31b3c5 | 417 | |
AnnaBridge | 172:7d866c31b3c5 | 418 | } |
AnnaBridge | 172:7d866c31b3c5 | 419 | |
AnnaBridge | 172:7d866c31b3c5 | 420 | /** |
AnnaBridge | 172:7d866c31b3c5 | 421 | * @brief Fill a CAM entry for MAC address comparison. |
AnnaBridge | 172:7d866c31b3c5 | 422 | * @param[in] u32Entry MAC entry to fill. Entry 0 is used to store device MAC address, do not overwrite the setting in it. |
AnnaBridge | 172:7d866c31b3c5 | 423 | * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address |
AnnaBridge | 172:7d866c31b3c5 | 424 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 425 | */ |
AnnaBridge | 172:7d866c31b3c5 | 426 | void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[]) |
AnnaBridge | 172:7d866c31b3c5 | 427 | { |
AnnaBridge | 172:7d866c31b3c5 | 428 | uint32_t u32Lsw, u32Msw; |
AnnaBridge | 172:7d866c31b3c5 | 429 | uint32_t reg; |
AnnaBridge | 172:7d866c31b3c5 | 430 | u32Lsw = (uint32_t)(((uint32_t)pu8MacAddr[4] << 24) | |
AnnaBridge | 172:7d866c31b3c5 | 431 | ((uint32_t)pu8MacAddr[5] << 16)); |
AnnaBridge | 172:7d866c31b3c5 | 432 | u32Msw = (uint32_t)(((uint32_t)pu8MacAddr[0] << 24)| |
AnnaBridge | 172:7d866c31b3c5 | 433 | ((uint32_t)pu8MacAddr[1] << 16)| |
AnnaBridge | 172:7d866c31b3c5 | 434 | ((uint32_t)pu8MacAddr[2] << 8)| |
AnnaBridge | 172:7d866c31b3c5 | 435 | (uint32_t)pu8MacAddr[3]); |
AnnaBridge | 172:7d866c31b3c5 | 436 | |
AnnaBridge | 172:7d866c31b3c5 | 437 | reg = (uint32_t)&EMAC->CAM0M + u32Entry * 2UL * 4UL; |
AnnaBridge | 172:7d866c31b3c5 | 438 | *(uint32_t volatile *)reg = u32Msw; |
AnnaBridge | 172:7d866c31b3c5 | 439 | reg = (uint32_t)&EMAC->CAM0L + u32Entry * 2UL * 4UL; |
AnnaBridge | 172:7d866c31b3c5 | 440 | *(uint32_t volatile *)reg = u32Lsw; |
AnnaBridge | 172:7d866c31b3c5 | 441 | |
AnnaBridge | 172:7d866c31b3c5 | 442 | EMAC->CAMEN |= (1UL << u32Entry); |
AnnaBridge | 172:7d866c31b3c5 | 443 | } |
AnnaBridge | 172:7d866c31b3c5 | 444 | |
AnnaBridge | 172:7d866c31b3c5 | 445 | /** |
AnnaBridge | 172:7d866c31b3c5 | 446 | * @brief Disable a specified CAM entry |
AnnaBridge | 172:7d866c31b3c5 | 447 | * @param[in] u32Entry CAM entry to be disabled |
AnnaBridge | 172:7d866c31b3c5 | 448 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 449 | */ |
AnnaBridge | 172:7d866c31b3c5 | 450 | void EMAC_DisableCamEntry(uint32_t u32Entry) |
AnnaBridge | 172:7d866c31b3c5 | 451 | { |
AnnaBridge | 172:7d866c31b3c5 | 452 | EMAC->CAMEN &= ~(1UL << u32Entry); |
AnnaBridge | 172:7d866c31b3c5 | 453 | } |
AnnaBridge | 172:7d866c31b3c5 | 454 | |
AnnaBridge | 172:7d866c31b3c5 | 455 | |
AnnaBridge | 172:7d866c31b3c5 | 456 | /** |
AnnaBridge | 172:7d866c31b3c5 | 457 | * @brief Receive an Ethernet packet |
AnnaBridge | 172:7d866c31b3c5 | 458 | * @param[in] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed) |
AnnaBridge | 172:7d866c31b3c5 | 459 | * @param[in] pu32Size Received packet size (without 4 byte CRC). |
AnnaBridge | 172:7d866c31b3c5 | 460 | * @return Packet receive success or not |
AnnaBridge | 172:7d866c31b3c5 | 461 | * @retval 0 No packet available for receive |
AnnaBridge | 172:7d866c31b3c5 | 462 | * @retval 1 A packet is received |
AnnaBridge | 172:7d866c31b3c5 | 463 | * @note Return 0 doesn't guarantee the packet will be sent and received successfully. |
AnnaBridge | 172:7d866c31b3c5 | 464 | */ |
AnnaBridge | 172:7d866c31b3c5 | 465 | uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size) |
AnnaBridge | 172:7d866c31b3c5 | 466 | { |
AnnaBridge | 172:7d866c31b3c5 | 467 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 468 | uint32_t status, reg; |
AnnaBridge | 172:7d866c31b3c5 | 469 | uint32_t u32Count = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 470 | |
AnnaBridge | 172:7d866c31b3c5 | 471 | /* Clear Rx interrupt flags */ |
AnnaBridge | 172:7d866c31b3c5 | 472 | reg = EMAC->INTSTS; |
AnnaBridge | 172:7d866c31b3c5 | 473 | EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all RX related interrupt status */ |
AnnaBridge | 172:7d866c31b3c5 | 474 | |
AnnaBridge | 172:7d866c31b3c5 | 475 | if (reg & EMAC_INTSTS_RXBEIF_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 476 | /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ |
AnnaBridge | 172:7d866c31b3c5 | 477 | while(1) {} |
AnnaBridge | 172:7d866c31b3c5 | 478 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 479 | |
AnnaBridge | 172:7d866c31b3c5 | 480 | /* Get Rx Frame Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 481 | desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 482 | |
AnnaBridge | 172:7d866c31b3c5 | 483 | /* If we reach last recv Rx descriptor, leave the loop */ |
AnnaBridge | 172:7d866c31b3c5 | 484 | if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { /* ownership=CPU */ |
AnnaBridge | 172:7d866c31b3c5 | 485 | |
AnnaBridge | 172:7d866c31b3c5 | 486 | status = desc->u32Status1 >> 16; |
AnnaBridge | 172:7d866c31b3c5 | 487 | |
AnnaBridge | 172:7d866c31b3c5 | 488 | /* If Rx frame is good, process received frame */ |
AnnaBridge | 172:7d866c31b3c5 | 489 | if(status & EMAC_RXFD_RXGD) { |
AnnaBridge | 172:7d866c31b3c5 | 490 | /* lower 16 bit in descriptor status1 stores the Rx packet length */ |
AnnaBridge | 172:7d866c31b3c5 | 491 | *pu32Size = desc->u32Status1 & 0xFFFFUL; |
AnnaBridge | 172:7d866c31b3c5 | 492 | memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size); |
AnnaBridge | 172:7d866c31b3c5 | 493 | u32Count = 1UL; |
AnnaBridge | 172:7d866c31b3c5 | 494 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 495 | /* Save Error status if necessary */ |
AnnaBridge | 172:7d866c31b3c5 | 496 | if (status & EMAC_RXFD_RP) {} |
AnnaBridge | 172:7d866c31b3c5 | 497 | if (status & EMAC_RXFD_ALIE) {} |
AnnaBridge | 172:7d866c31b3c5 | 498 | if (status & EMAC_RXFD_PTLE) {} |
AnnaBridge | 172:7d866c31b3c5 | 499 | if (status & EMAC_RXFD_CRCE) {} |
AnnaBridge | 172:7d866c31b3c5 | 500 | } |
AnnaBridge | 172:7d866c31b3c5 | 501 | } |
AnnaBridge | 172:7d866c31b3c5 | 502 | } |
AnnaBridge | 172:7d866c31b3c5 | 503 | return(u32Count); |
AnnaBridge | 172:7d866c31b3c5 | 504 | } |
AnnaBridge | 172:7d866c31b3c5 | 505 | |
AnnaBridge | 172:7d866c31b3c5 | 506 | /** |
AnnaBridge | 172:7d866c31b3c5 | 507 | * @brief Receive an Ethernet packet and the time stamp while it's received |
AnnaBridge | 172:7d866c31b3c5 | 508 | * @param[out] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed) |
AnnaBridge | 172:7d866c31b3c5 | 509 | * @param[out] pu32Size Received packet size (without 4 byte CRC). |
AnnaBridge | 172:7d866c31b3c5 | 510 | * @param[out] pu32Sec Second value while packet sent |
AnnaBridge | 172:7d866c31b3c5 | 511 | * @param[out] pu32Nsec Nano second value while packet sent |
AnnaBridge | 172:7d866c31b3c5 | 512 | * @return Packet receive success or not |
AnnaBridge | 172:7d866c31b3c5 | 513 | * @retval 0 No packet available for receive |
AnnaBridge | 172:7d866c31b3c5 | 514 | * @retval 1 A packet is received |
AnnaBridge | 172:7d866c31b3c5 | 515 | * @note Return 0 doesn't guarantee the packet will be sent and received successfully. |
AnnaBridge | 172:7d866c31b3c5 | 516 | * @note Largest Ethernet packet is 1514 bytes after stripped CRC, application must give |
AnnaBridge | 172:7d866c31b3c5 | 517 | * a buffer large enough to store such packet |
AnnaBridge | 172:7d866c31b3c5 | 518 | */ |
AnnaBridge | 172:7d866c31b3c5 | 519 | uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 520 | { |
AnnaBridge | 172:7d866c31b3c5 | 521 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 522 | uint32_t status, reg; |
AnnaBridge | 172:7d866c31b3c5 | 523 | uint32_t u32Count = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 524 | |
AnnaBridge | 172:7d866c31b3c5 | 525 | /* Clear Rx interrupt flags */ |
AnnaBridge | 172:7d866c31b3c5 | 526 | reg = EMAC->INTSTS; |
AnnaBridge | 172:7d866c31b3c5 | 527 | EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all Rx related interrupt status */ |
AnnaBridge | 172:7d866c31b3c5 | 528 | |
AnnaBridge | 172:7d866c31b3c5 | 529 | if (reg & EMAC_INTSTS_RXBEIF_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 530 | /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ |
AnnaBridge | 172:7d866c31b3c5 | 531 | while(1) {} |
AnnaBridge | 172:7d866c31b3c5 | 532 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 533 | |
AnnaBridge | 172:7d866c31b3c5 | 534 | /* Get Rx Frame Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 535 | desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 536 | |
AnnaBridge | 172:7d866c31b3c5 | 537 | /* If we reach last recv Rx descriptor, leave the loop */ |
AnnaBridge | 172:7d866c31b3c5 | 538 | if(EMAC->CRXDSA != (uint32_t)desc) { |
AnnaBridge | 172:7d866c31b3c5 | 539 | if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { /* ownership=CPU */ |
AnnaBridge | 172:7d866c31b3c5 | 540 | |
AnnaBridge | 172:7d866c31b3c5 | 541 | status = desc->u32Status1 >> 16; |
AnnaBridge | 172:7d866c31b3c5 | 542 | |
AnnaBridge | 172:7d866c31b3c5 | 543 | /* If Rx frame is good, process received frame */ |
AnnaBridge | 172:7d866c31b3c5 | 544 | if(status & EMAC_RXFD_RXGD) { |
AnnaBridge | 172:7d866c31b3c5 | 545 | /* lower 16 bit in descriptor status1 stores the Rx packet length */ |
AnnaBridge | 172:7d866c31b3c5 | 546 | *pu32Size = desc->u32Status1 & 0xFFFFUL; |
AnnaBridge | 172:7d866c31b3c5 | 547 | memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size); |
AnnaBridge | 172:7d866c31b3c5 | 548 | |
AnnaBridge | 172:7d866c31b3c5 | 549 | *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */ |
AnnaBridge | 172:7d866c31b3c5 | 550 | *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */ |
AnnaBridge | 172:7d866c31b3c5 | 551 | |
AnnaBridge | 172:7d866c31b3c5 | 552 | u32Count = 1UL; |
AnnaBridge | 172:7d866c31b3c5 | 553 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 554 | /* Save Error status if necessary */ |
AnnaBridge | 172:7d866c31b3c5 | 555 | if (status & EMAC_RXFD_RP) {} |
AnnaBridge | 172:7d866c31b3c5 | 556 | if (status & EMAC_RXFD_ALIE) {} |
AnnaBridge | 172:7d866c31b3c5 | 557 | if (status & EMAC_RXFD_PTLE) {} |
AnnaBridge | 172:7d866c31b3c5 | 558 | if (status & EMAC_RXFD_CRCE) {} |
AnnaBridge | 172:7d866c31b3c5 | 559 | } |
AnnaBridge | 172:7d866c31b3c5 | 560 | } |
AnnaBridge | 172:7d866c31b3c5 | 561 | } |
AnnaBridge | 172:7d866c31b3c5 | 562 | } |
AnnaBridge | 172:7d866c31b3c5 | 563 | return(u32Count); |
AnnaBridge | 172:7d866c31b3c5 | 564 | } |
AnnaBridge | 172:7d866c31b3c5 | 565 | |
AnnaBridge | 172:7d866c31b3c5 | 566 | /** |
AnnaBridge | 172:7d866c31b3c5 | 567 | * @brief Clean up process after a packet is received |
AnnaBridge | 172:7d866c31b3c5 | 568 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 569 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 570 | * @details EMAC Rx interrupt service routine \b must call this API to release the resource use by receive process |
AnnaBridge | 172:7d866c31b3c5 | 571 | * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1 |
AnnaBridge | 172:7d866c31b3c5 | 572 | */ |
AnnaBridge | 172:7d866c31b3c5 | 573 | void EMAC_RecvPktDone(void) |
AnnaBridge | 172:7d866c31b3c5 | 574 | { |
AnnaBridge | 172:7d866c31b3c5 | 575 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 576 | /* Get Rx Frame Descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 577 | desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 578 | |
AnnaBridge | 172:7d866c31b3c5 | 579 | /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ |
AnnaBridge | 172:7d866c31b3c5 | 580 | desc->u32Data = desc->u32Backup1; |
AnnaBridge | 172:7d866c31b3c5 | 581 | desc->u32Next = desc->u32Backup2; |
AnnaBridge | 172:7d866c31b3c5 | 582 | |
AnnaBridge | 172:7d866c31b3c5 | 583 | /* Get Next Frame Descriptor pointer to process */ |
AnnaBridge | 172:7d866c31b3c5 | 584 | desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; |
AnnaBridge | 172:7d866c31b3c5 | 585 | |
AnnaBridge | 172:7d866c31b3c5 | 586 | /* Save last processed Rx descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 587 | u32CurrentRxDesc = (uint32_t)desc; |
AnnaBridge | 172:7d866c31b3c5 | 588 | |
AnnaBridge | 172:7d866c31b3c5 | 589 | /* Change ownership to DMA for next use */ |
AnnaBridge | 172:7d866c31b3c5 | 590 | desc->u32Status1 |= EMAC_DESC_OWN_EMAC; |
AnnaBridge | 172:7d866c31b3c5 | 591 | |
AnnaBridge | 172:7d866c31b3c5 | 592 | EMAC_TRIGGER_RX(); |
AnnaBridge | 172:7d866c31b3c5 | 593 | } |
AnnaBridge | 172:7d866c31b3c5 | 594 | |
AnnaBridge | 172:7d866c31b3c5 | 595 | |
AnnaBridge | 172:7d866c31b3c5 | 596 | /** |
AnnaBridge | 172:7d866c31b3c5 | 597 | * @brief Send an Ethernet packet |
AnnaBridge | 172:7d866c31b3c5 | 598 | * @param[in] pu8Data Pointer to a buffer holds the packet to transmit |
AnnaBridge | 172:7d866c31b3c5 | 599 | * @param[in] u32Size Packet size (without 4 byte CRC). |
AnnaBridge | 172:7d866c31b3c5 | 600 | * @return Packet transmit success or not |
AnnaBridge | 172:7d866c31b3c5 | 601 | * @retval 0 Transmit failed due to descriptor unavailable. |
AnnaBridge | 172:7d866c31b3c5 | 602 | * @retval 1 Packet is copied to descriptor and triggered to transmit. |
AnnaBridge | 172:7d866c31b3c5 | 603 | * @note Return 1 doesn't guarantee the packet will be sent and received successfully. |
AnnaBridge | 172:7d866c31b3c5 | 604 | */ |
AnnaBridge | 172:7d866c31b3c5 | 605 | uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size) |
AnnaBridge | 172:7d866c31b3c5 | 606 | { |
AnnaBridge | 172:7d866c31b3c5 | 607 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 608 | uint32_t status; |
AnnaBridge | 172:7d866c31b3c5 | 609 | uint32_t ret = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 610 | /* Get Tx frame descriptor & data pointer */ |
AnnaBridge | 172:7d866c31b3c5 | 611 | desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 612 | |
AnnaBridge | 172:7d866c31b3c5 | 613 | status = desc->u32Status1; |
AnnaBridge | 172:7d866c31b3c5 | 614 | |
AnnaBridge | 172:7d866c31b3c5 | 615 | /* Check descriptor ownership */ |
AnnaBridge | 172:7d866c31b3c5 | 616 | if((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { |
AnnaBridge | 172:7d866c31b3c5 | 617 | memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size); |
AnnaBridge | 172:7d866c31b3c5 | 618 | |
AnnaBridge | 172:7d866c31b3c5 | 619 | /* Set Tx descriptor transmit byte count */ |
AnnaBridge | 172:7d866c31b3c5 | 620 | desc->u32Status2 = u32Size; |
AnnaBridge | 172:7d866c31b3c5 | 621 | |
AnnaBridge | 172:7d866c31b3c5 | 622 | /* Change descriptor ownership to EMAC */ |
AnnaBridge | 172:7d866c31b3c5 | 623 | desc->u32Status1 |= EMAC_DESC_OWN_EMAC; |
AnnaBridge | 172:7d866c31b3c5 | 624 | |
AnnaBridge | 172:7d866c31b3c5 | 625 | /* Get next Tx descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 626 | u32NextTxDesc = (uint32_t)(desc->u32Next); |
AnnaBridge | 172:7d866c31b3c5 | 627 | |
AnnaBridge | 172:7d866c31b3c5 | 628 | /* Trigger EMAC to send the packet */ |
AnnaBridge | 172:7d866c31b3c5 | 629 | EMAC_TRIGGER_TX(); |
AnnaBridge | 172:7d866c31b3c5 | 630 | ret = 1UL; |
AnnaBridge | 172:7d866c31b3c5 | 631 | } |
AnnaBridge | 172:7d866c31b3c5 | 632 | return(ret); |
AnnaBridge | 172:7d866c31b3c5 | 633 | } |
AnnaBridge | 172:7d866c31b3c5 | 634 | |
AnnaBridge | 172:7d866c31b3c5 | 635 | |
AnnaBridge | 172:7d866c31b3c5 | 636 | /** |
AnnaBridge | 172:7d866c31b3c5 | 637 | * @brief Clean up process after packet(s) are sent |
AnnaBridge | 172:7d866c31b3c5 | 638 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 639 | * @return Number of packet sent between two function calls |
AnnaBridge | 172:7d866c31b3c5 | 640 | * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDoneTS to |
AnnaBridge | 172:7d866c31b3c5 | 641 | * release the resource use by transmit process |
AnnaBridge | 172:7d866c31b3c5 | 642 | */ |
AnnaBridge | 172:7d866c31b3c5 | 643 | uint32_t EMAC_SendPktDone(void) |
AnnaBridge | 172:7d866c31b3c5 | 644 | { |
AnnaBridge | 172:7d866c31b3c5 | 645 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 646 | uint32_t status, reg; |
AnnaBridge | 172:7d866c31b3c5 | 647 | uint32_t last_tx_desc; |
AnnaBridge | 172:7d866c31b3c5 | 648 | uint32_t u32Count = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 649 | |
AnnaBridge | 172:7d866c31b3c5 | 650 | reg = EMAC->INTSTS; |
AnnaBridge | 172:7d866c31b3c5 | 651 | /* Clear Tx interrupt flags */ |
AnnaBridge | 172:7d866c31b3c5 | 652 | EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk); |
AnnaBridge | 172:7d866c31b3c5 | 653 | |
AnnaBridge | 172:7d866c31b3c5 | 654 | |
AnnaBridge | 172:7d866c31b3c5 | 655 | if (reg & EMAC_INTSTS_TXBEIF_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 656 | /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ |
AnnaBridge | 172:7d866c31b3c5 | 657 | while(1) {} |
AnnaBridge | 172:7d866c31b3c5 | 658 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 659 | /* Process the descriptor(s). */ |
AnnaBridge | 172:7d866c31b3c5 | 660 | last_tx_desc = EMAC->CTXDSA ; |
AnnaBridge | 172:7d866c31b3c5 | 661 | /* Get our first descriptor to process */ |
AnnaBridge | 172:7d866c31b3c5 | 662 | desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 663 | do { |
AnnaBridge | 172:7d866c31b3c5 | 664 | /* Descriptor ownership is still EMAC, so this packet haven't been send. */ |
AnnaBridge | 172:7d866c31b3c5 | 665 | if(desc->u32Status1 & EMAC_DESC_OWN_EMAC) { |
AnnaBridge | 172:7d866c31b3c5 | 666 | break; |
AnnaBridge | 172:7d866c31b3c5 | 667 | } |
AnnaBridge | 172:7d866c31b3c5 | 668 | /* Get Tx status stored in descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 669 | status = desc->u32Status2 >> 16UL; |
AnnaBridge | 172:7d866c31b3c5 | 670 | if (status & EMAC_TXFD_TXCP) { |
AnnaBridge | 172:7d866c31b3c5 | 671 | u32Count++; |
AnnaBridge | 172:7d866c31b3c5 | 672 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 673 | /* Do nothing here on error. */ |
AnnaBridge | 172:7d866c31b3c5 | 674 | if (status & EMAC_TXFD_TXABT) {} |
AnnaBridge | 172:7d866c31b3c5 | 675 | if (status & EMAC_TXFD_DEF) {} |
AnnaBridge | 172:7d866c31b3c5 | 676 | if (status & EMAC_TXFD_PAU) {} |
AnnaBridge | 172:7d866c31b3c5 | 677 | if (status & EMAC_TXFD_EXDEF) {} |
AnnaBridge | 172:7d866c31b3c5 | 678 | if (status & EMAC_TXFD_NCS) {} |
AnnaBridge | 172:7d866c31b3c5 | 679 | if (status & EMAC_TXFD_SQE) {} |
AnnaBridge | 172:7d866c31b3c5 | 680 | if (status & EMAC_TXFD_LC) {} |
AnnaBridge | 172:7d866c31b3c5 | 681 | if (status & EMAC_TXFD_TXHA) {} |
AnnaBridge | 172:7d866c31b3c5 | 682 | } |
AnnaBridge | 172:7d866c31b3c5 | 683 | |
AnnaBridge | 172:7d866c31b3c5 | 684 | /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ |
AnnaBridge | 172:7d866c31b3c5 | 685 | desc->u32Data = desc->u32Backup1; |
AnnaBridge | 172:7d866c31b3c5 | 686 | desc->u32Next = desc->u32Backup2; |
AnnaBridge | 172:7d866c31b3c5 | 687 | /* go to next descriptor in link */ |
AnnaBridge | 172:7d866c31b3c5 | 688 | desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; |
AnnaBridge | 172:7d866c31b3c5 | 689 | } while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */ |
AnnaBridge | 172:7d866c31b3c5 | 690 | /* Save last processed Tx descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 691 | u32CurrentTxDesc = (uint32_t)desc; |
AnnaBridge | 172:7d866c31b3c5 | 692 | } |
AnnaBridge | 172:7d866c31b3c5 | 693 | return(u32Count); |
AnnaBridge | 172:7d866c31b3c5 | 694 | } |
AnnaBridge | 172:7d866c31b3c5 | 695 | |
AnnaBridge | 172:7d866c31b3c5 | 696 | /** |
AnnaBridge | 172:7d866c31b3c5 | 697 | * @brief Clean up process after a packet is sent, and get the time stamp while packet is sent |
AnnaBridge | 172:7d866c31b3c5 | 698 | * @param[in] pu32Sec Second value while packet sent |
AnnaBridge | 172:7d866c31b3c5 | 699 | * @param[in] pu32Nsec Nano second value while packet sent |
AnnaBridge | 172:7d866c31b3c5 | 700 | * @return If a packet sent successfully |
AnnaBridge | 172:7d866c31b3c5 | 701 | * @retval 0 No packet sent successfully, and the value in *pu32Sec and *pu32Nsec are meaningless |
AnnaBridge | 172:7d866c31b3c5 | 702 | * @retval 1 A packet sent successfully, and the value in *pu32Sec and *pu32Nsec is the time stamp while packet sent |
AnnaBridge | 172:7d866c31b3c5 | 703 | * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDone to |
AnnaBridge | 172:7d866c31b3c5 | 704 | * release the resource use by transmit process |
AnnaBridge | 172:7d866c31b3c5 | 705 | */ |
AnnaBridge | 172:7d866c31b3c5 | 706 | uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 707 | { |
AnnaBridge | 172:7d866c31b3c5 | 708 | |
AnnaBridge | 172:7d866c31b3c5 | 709 | EMAC_DESCRIPTOR_T *desc; |
AnnaBridge | 172:7d866c31b3c5 | 710 | uint32_t status, reg; |
AnnaBridge | 172:7d866c31b3c5 | 711 | uint32_t u32Count = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 712 | |
AnnaBridge | 172:7d866c31b3c5 | 713 | reg = EMAC->INTSTS; |
AnnaBridge | 172:7d866c31b3c5 | 714 | /* Clear Tx interrupt flags */ |
AnnaBridge | 172:7d866c31b3c5 | 715 | EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk); |
AnnaBridge | 172:7d866c31b3c5 | 716 | |
AnnaBridge | 172:7d866c31b3c5 | 717 | |
AnnaBridge | 172:7d866c31b3c5 | 718 | if (reg & EMAC_INTSTS_TXBEIF_Msk) { |
AnnaBridge | 172:7d866c31b3c5 | 719 | /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */ |
AnnaBridge | 172:7d866c31b3c5 | 720 | while(1) {} |
AnnaBridge | 172:7d866c31b3c5 | 721 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 722 | /* Process the descriptor. |
AnnaBridge | 172:7d866c31b3c5 | 723 | Get our first descriptor to process */ |
AnnaBridge | 172:7d866c31b3c5 | 724 | desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc; |
AnnaBridge | 172:7d866c31b3c5 | 725 | |
AnnaBridge | 172:7d866c31b3c5 | 726 | /* Descriptor ownership is still EMAC, so this packet haven't been send. */ |
AnnaBridge | 172:7d866c31b3c5 | 727 | if((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { |
AnnaBridge | 172:7d866c31b3c5 | 728 | /* Get Tx status stored in descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 729 | status = desc->u32Status2 >> 16UL; |
AnnaBridge | 172:7d866c31b3c5 | 730 | if (status & EMAC_TXFD_TXCP) { |
AnnaBridge | 172:7d866c31b3c5 | 731 | u32Count = 1UL; |
AnnaBridge | 172:7d866c31b3c5 | 732 | *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */ |
AnnaBridge | 172:7d866c31b3c5 | 733 | *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */ |
AnnaBridge | 172:7d866c31b3c5 | 734 | } else { |
AnnaBridge | 172:7d866c31b3c5 | 735 | /* Do nothing here on error. */ |
AnnaBridge | 172:7d866c31b3c5 | 736 | if (status & EMAC_TXFD_TXABT) {} |
AnnaBridge | 172:7d866c31b3c5 | 737 | if (status & EMAC_TXFD_DEF) {} |
AnnaBridge | 172:7d866c31b3c5 | 738 | if (status & EMAC_TXFD_PAU) {} |
AnnaBridge | 172:7d866c31b3c5 | 739 | if (status & EMAC_TXFD_EXDEF) {} |
AnnaBridge | 172:7d866c31b3c5 | 740 | if (status & EMAC_TXFD_NCS) {} |
AnnaBridge | 172:7d866c31b3c5 | 741 | if (status & EMAC_TXFD_SQE) {} |
AnnaBridge | 172:7d866c31b3c5 | 742 | if (status & EMAC_TXFD_LC) {} |
AnnaBridge | 172:7d866c31b3c5 | 743 | if (status & EMAC_TXFD_TXHA) {} |
AnnaBridge | 172:7d866c31b3c5 | 744 | } |
AnnaBridge | 172:7d866c31b3c5 | 745 | |
AnnaBridge | 172:7d866c31b3c5 | 746 | /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */ |
AnnaBridge | 172:7d866c31b3c5 | 747 | desc->u32Data = desc->u32Backup1; |
AnnaBridge | 172:7d866c31b3c5 | 748 | desc->u32Next = desc->u32Backup2; |
AnnaBridge | 172:7d866c31b3c5 | 749 | /* go to next descriptor in link */ |
AnnaBridge | 172:7d866c31b3c5 | 750 | desc = (EMAC_DESCRIPTOR_T *)desc->u32Next; |
AnnaBridge | 172:7d866c31b3c5 | 751 | |
AnnaBridge | 172:7d866c31b3c5 | 752 | /* Save last processed Tx descriptor */ |
AnnaBridge | 172:7d866c31b3c5 | 753 | u32CurrentTxDesc = (uint32_t)desc; |
AnnaBridge | 172:7d866c31b3c5 | 754 | } |
AnnaBridge | 172:7d866c31b3c5 | 755 | } |
AnnaBridge | 172:7d866c31b3c5 | 756 | |
AnnaBridge | 172:7d866c31b3c5 | 757 | return(u32Count); |
AnnaBridge | 172:7d866c31b3c5 | 758 | } |
AnnaBridge | 172:7d866c31b3c5 | 759 | |
AnnaBridge | 172:7d866c31b3c5 | 760 | /** |
AnnaBridge | 172:7d866c31b3c5 | 761 | * @brief Enable IEEE1588 time stamp function and set current time |
AnnaBridge | 172:7d866c31b3c5 | 762 | * @param[in] u32Sec Second value |
AnnaBridge | 172:7d866c31b3c5 | 763 | * @param[in] u32Nsec Nano second value |
AnnaBridge | 172:7d866c31b3c5 | 764 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 765 | */ |
AnnaBridge | 172:7d866c31b3c5 | 766 | void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 767 | { |
AnnaBridge | 172:7d866c31b3c5 | 768 | double f; |
AnnaBridge | 172:7d866c31b3c5 | 769 | uint32_t reg; |
AnnaBridge | 172:7d866c31b3c5 | 770 | EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 771 | EMAC->UPDSEC = u32Sec; /* Assume current time is 0 sec + 0 nano sec */ |
AnnaBridge | 172:7d866c31b3c5 | 772 | EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); |
AnnaBridge | 172:7d866c31b3c5 | 773 | |
AnnaBridge | 172:7d866c31b3c5 | 774 | /* PTP source clock is 160MHz (Real chip using PLL). Each tick is 6.25ns |
AnnaBridge | 172:7d866c31b3c5 | 775 | Assume we want to set each tick to 100ns. |
AnnaBridge | 172:7d866c31b3c5 | 776 | Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 |
AnnaBridge | 172:7d866c31b3c5 | 777 | Addend register = 2^32 * tick_freq / (160MHz), where tick_freq = (2^31 / 215) MHz |
AnnaBridge | 172:7d866c31b3c5 | 778 | From above equation, addend register = 2^63 / (160M * 215) ~= 268121280 = 0xFFB34C0 |
AnnaBridge | 172:7d866c31b3c5 | 779 | So: |
AnnaBridge | 172:7d866c31b3c5 | 780 | EMAC->TSIR = 0xD7; |
AnnaBridge | 172:7d866c31b3c5 | 781 | EMAC->TSAR = 0x1E70C600; */ |
AnnaBridge | 172:7d866c31b3c5 | 782 | f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5; |
AnnaBridge | 172:7d866c31b3c5 | 783 | EMAC->TSINC = (reg = (uint32_t)f); |
AnnaBridge | 172:7d866c31b3c5 | 784 | f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg); |
AnnaBridge | 172:7d866c31b3c5 | 785 | EMAC->TSADDEND = (uint32_t)f; |
AnnaBridge | 172:7d866c31b3c5 | 786 | EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); /* Fine update */ |
AnnaBridge | 172:7d866c31b3c5 | 787 | } |
AnnaBridge | 172:7d866c31b3c5 | 788 | |
AnnaBridge | 172:7d866c31b3c5 | 789 | /** |
AnnaBridge | 172:7d866c31b3c5 | 790 | * @brief Disable IEEE1588 time stamp function |
AnnaBridge | 172:7d866c31b3c5 | 791 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 792 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 793 | */ |
AnnaBridge | 172:7d866c31b3c5 | 794 | void EMAC_DisableTS(void) |
AnnaBridge | 172:7d866c31b3c5 | 795 | { |
AnnaBridge | 172:7d866c31b3c5 | 796 | EMAC->TSCTL = 0UL; |
AnnaBridge | 172:7d866c31b3c5 | 797 | } |
AnnaBridge | 172:7d866c31b3c5 | 798 | |
AnnaBridge | 172:7d866c31b3c5 | 799 | /** |
AnnaBridge | 172:7d866c31b3c5 | 800 | * @brief Get current time stamp |
AnnaBridge | 172:7d866c31b3c5 | 801 | * @param[out] pu32Sec Current second value |
AnnaBridge | 172:7d866c31b3c5 | 802 | * @param[out] pu32Nsec Current nano second value |
AnnaBridge | 172:7d866c31b3c5 | 803 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 804 | */ |
AnnaBridge | 172:7d866c31b3c5 | 805 | void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 806 | { |
AnnaBridge | 172:7d866c31b3c5 | 807 | /* Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read. */ |
AnnaBridge | 172:7d866c31b3c5 | 808 | *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC); |
AnnaBridge | 172:7d866c31b3c5 | 809 | *pu32Sec = EMAC->TSSEC; |
AnnaBridge | 172:7d866c31b3c5 | 810 | } |
AnnaBridge | 172:7d866c31b3c5 | 811 | |
AnnaBridge | 172:7d866c31b3c5 | 812 | /** |
AnnaBridge | 172:7d866c31b3c5 | 813 | * @brief Set current time stamp |
AnnaBridge | 172:7d866c31b3c5 | 814 | * @param[in] u32Sec Second value |
AnnaBridge | 172:7d866c31b3c5 | 815 | * @param[in] u32Nsec Nano second value |
AnnaBridge | 172:7d866c31b3c5 | 816 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 817 | */ |
AnnaBridge | 172:7d866c31b3c5 | 818 | void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 819 | { |
AnnaBridge | 172:7d866c31b3c5 | 820 | /* Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk) */ |
AnnaBridge | 172:7d866c31b3c5 | 821 | EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 822 | EMAC->UPDSEC = u32Sec; |
AnnaBridge | 172:7d866c31b3c5 | 823 | EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); |
AnnaBridge | 172:7d866c31b3c5 | 824 | EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); |
AnnaBridge | 172:7d866c31b3c5 | 825 | |
AnnaBridge | 172:7d866c31b3c5 | 826 | } |
AnnaBridge | 172:7d866c31b3c5 | 827 | |
AnnaBridge | 172:7d866c31b3c5 | 828 | /** |
AnnaBridge | 172:7d866c31b3c5 | 829 | * @brief Enable alarm function and set alarm time |
AnnaBridge | 172:7d866c31b3c5 | 830 | * @param[in] u32Sec Second value to trigger alarm |
AnnaBridge | 172:7d866c31b3c5 | 831 | * @param[in] u32Nsec Nano second value to trigger alarm |
AnnaBridge | 172:7d866c31b3c5 | 832 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 833 | */ |
AnnaBridge | 172:7d866c31b3c5 | 834 | void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 835 | { |
AnnaBridge | 172:7d866c31b3c5 | 836 | |
AnnaBridge | 172:7d866c31b3c5 | 837 | EMAC->ALMSEC = u32Sec; |
AnnaBridge | 172:7d866c31b3c5 | 838 | EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec); |
AnnaBridge | 172:7d866c31b3c5 | 839 | EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 840 | |
AnnaBridge | 172:7d866c31b3c5 | 841 | } |
AnnaBridge | 172:7d866c31b3c5 | 842 | |
AnnaBridge | 172:7d866c31b3c5 | 843 | /** |
AnnaBridge | 172:7d866c31b3c5 | 844 | * @brief Disable alarm function |
AnnaBridge | 172:7d866c31b3c5 | 845 | * @param None |
AnnaBridge | 172:7d866c31b3c5 | 846 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 847 | */ |
AnnaBridge | 172:7d866c31b3c5 | 848 | void EMAC_DisableAlarm(void) |
AnnaBridge | 172:7d866c31b3c5 | 849 | { |
AnnaBridge | 172:7d866c31b3c5 | 850 | |
AnnaBridge | 172:7d866c31b3c5 | 851 | EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 852 | |
AnnaBridge | 172:7d866c31b3c5 | 853 | } |
AnnaBridge | 172:7d866c31b3c5 | 854 | |
AnnaBridge | 172:7d866c31b3c5 | 855 | /** |
AnnaBridge | 172:7d866c31b3c5 | 856 | * @brief Add a offset to current time |
AnnaBridge | 172:7d866c31b3c5 | 857 | * @param[in] u32Neg Offset is negative value (u32Neg == 1) or positive value (u32Neg == 0). |
AnnaBridge | 172:7d866c31b3c5 | 858 | * @param[in] u32Sec Second value to add to current time |
AnnaBridge | 172:7d866c31b3c5 | 859 | * @param[in] u32Nsec Nano second value to add to current time |
AnnaBridge | 172:7d866c31b3c5 | 860 | * @return None |
AnnaBridge | 172:7d866c31b3c5 | 861 | */ |
AnnaBridge | 172:7d866c31b3c5 | 862 | void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec) |
AnnaBridge | 172:7d866c31b3c5 | 863 | { |
AnnaBridge | 172:7d866c31b3c5 | 864 | EMAC->UPDSEC = u32Sec; |
AnnaBridge | 172:7d866c31b3c5 | 865 | EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec); |
AnnaBridge | 172:7d866c31b3c5 | 866 | if(u32Neg) { |
AnnaBridge | 172:7d866c31b3c5 | 867 | EMAC->UPDSUBSEC |= BIT31; /* Set bit 31 indicates this is a negative value */ |
AnnaBridge | 172:7d866c31b3c5 | 868 | } |
AnnaBridge | 172:7d866c31b3c5 | 869 | EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk; |
AnnaBridge | 172:7d866c31b3c5 | 870 | |
AnnaBridge | 172:7d866c31b3c5 | 871 | } |
AnnaBridge | 172:7d866c31b3c5 | 872 | |
AnnaBridge | 172:7d866c31b3c5 | 873 | |
AnnaBridge | 172:7d866c31b3c5 | 874 | /*@}*/ /* end of group M480_EMAC_EXPORTED_FUNCTIONS */ |
AnnaBridge | 172:7d866c31b3c5 | 875 | |
AnnaBridge | 172:7d866c31b3c5 | 876 | /*@}*/ /* end of group M480_EMAC_Driver */ |
AnnaBridge | 172:7d866c31b3c5 | 877 | |
AnnaBridge | 172:7d866c31b3c5 | 878 | /*@}*/ /* end of group M480_Device_Driver */ |
AnnaBridge | 172:7d866c31b3c5 | 879 | |
AnnaBridge | 172:7d866c31b3c5 | 880 | /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ |