A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.
Dependents: oldheating gps motorhome heating
link/nic.cpp@59:e0e556c8bd46, 2017-12-14 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Dec 14 20:55:40 2017 +0000
- Revision:
- 59:e0e556c8bd46
- Child:
- 60:1d8c7a1e7483
Added buffer length to help avoid over runs
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 59:e0e556c8bd46 | 1 | #include "mbed.h" |
andrewboyson | 59:e0e556c8bd46 | 2 | #include "nicdefs.h" |
andrewboyson | 59:e0e556c8bd46 | 3 | #include "log.h" |
andrewboyson | 59:e0e556c8bd46 | 4 | |
andrewboyson | 59:e0e556c8bd46 | 5 | #define NUM_RX_FRAMES 3 // Number of Rx Frames (== packets) |
andrewboyson | 59:e0e556c8bd46 | 6 | #define NUM_TX_FRAMES 2 // Number of Tx Frames (== packets) |
andrewboyson | 59:e0e556c8bd46 | 7 | |
andrewboyson | 59:e0e556c8bd46 | 8 | #define ETH_FRAME_LEN 1536 // Maximum Ethernet Frame Size |
andrewboyson | 59:e0e556c8bd46 | 9 | |
andrewboyson | 59:e0e556c8bd46 | 10 | static volatile uint8_t r_buff[NUM_RX_FRAMES][ETH_FRAME_LEN]; |
andrewboyson | 59:e0e556c8bd46 | 11 | static volatile uint8_t t_buff[NUM_TX_FRAMES][ETH_FRAME_LEN]; |
andrewboyson | 59:e0e556c8bd46 | 12 | static volatile RX_DESC_TypeDef r_desc[NUM_RX_FRAMES]; |
andrewboyson | 59:e0e556c8bd46 | 13 | static volatile __align(8) RX_STAT_TypeDef r_stat[NUM_RX_FRAMES]; //Must be aligned on an 8 byte boundary |
andrewboyson | 59:e0e556c8bd46 | 14 | static volatile TX_DESC_TypeDef t_desc[NUM_TX_FRAMES]; |
andrewboyson | 59:e0e556c8bd46 | 15 | static volatile TX_STAT_TypeDef t_stat[NUM_TX_FRAMES]; |
andrewboyson | 59:e0e556c8bd46 | 16 | |
andrewboyson | 59:e0e556c8bd46 | 17 | char* NicGetReceivedPacketOrNull(int* pSize) |
andrewboyson | 59:e0e556c8bd46 | 18 | { |
andrewboyson | 59:e0e556c8bd46 | 19 | if (LPC_EMAC->RxProduceIndex == LPC_EMAC->RxConsumeIndex) return NULL; |
andrewboyson | 59:e0e556c8bd46 | 20 | |
andrewboyson | 59:e0e556c8bd46 | 21 | uint32_t info = r_stat[LPC_EMAC->RxConsumeIndex].Info; |
andrewboyson | 59:e0e556c8bd46 | 22 | *pSize = (info & RINFO_SIZE) + 1 - 4; // exclude checksum |
andrewboyson | 59:e0e556c8bd46 | 23 | |
andrewboyson | 59:e0e556c8bd46 | 24 | return (char*)r_buff[LPC_EMAC->RxConsumeIndex]; |
andrewboyson | 59:e0e556c8bd46 | 25 | } |
andrewboyson | 59:e0e556c8bd46 | 26 | void NicReleaseReceivedPacket() |
andrewboyson | 59:e0e556c8bd46 | 27 | { |
andrewboyson | 59:e0e556c8bd46 | 28 | if (LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxDescriptorNumber) LPC_EMAC->RxConsumeIndex = 0; |
andrewboyson | 59:e0e556c8bd46 | 29 | else LPC_EMAC->RxConsumeIndex++; |
andrewboyson | 59:e0e556c8bd46 | 30 | } |
andrewboyson | 59:e0e556c8bd46 | 31 | char* NicGetTransmitPacketOrNull(int* pSize) |
andrewboyson | 59:e0e556c8bd46 | 32 | { |
andrewboyson | 59:e0e556c8bd46 | 33 | if (LPC_EMAC->TxConsumeIndex == 0 && LPC_EMAC->TxProduceIndex == LPC_EMAC->TxDescriptorNumber) return NULL; |
andrewboyson | 59:e0e556c8bd46 | 34 | if (LPC_EMAC->TxProduceIndex == LPC_EMAC->TxConsumeIndex - 1) return NULL; |
andrewboyson | 59:e0e556c8bd46 | 35 | *pSize = ETH_FRAME_LEN - 4; |
andrewboyson | 59:e0e556c8bd46 | 36 | return (char*)t_buff[LPC_EMAC->TxProduceIndex]; |
andrewboyson | 59:e0e556c8bd46 | 37 | } |
andrewboyson | 59:e0e556c8bd46 | 38 | void NicSendTransmitPacket(int size) |
andrewboyson | 59:e0e556c8bd46 | 39 | { |
andrewboyson | 59:e0e556c8bd46 | 40 | if (size == 0) return; |
andrewboyson | 59:e0e556c8bd46 | 41 | t_desc[LPC_EMAC->TxProduceIndex].Ctrl = (size - 1) | (TCTRL_INT | TCTRL_LAST); |
andrewboyson | 59:e0e556c8bd46 | 42 | if (LPC_EMAC->TxProduceIndex == LPC_EMAC->TxDescriptorNumber) LPC_EMAC->TxProduceIndex = 0; |
andrewboyson | 59:e0e556c8bd46 | 43 | else LPC_EMAC->TxProduceIndex++; |
andrewboyson | 59:e0e556c8bd46 | 44 | } |
andrewboyson | 59:e0e556c8bd46 | 45 | |
andrewboyson | 59:e0e556c8bd46 | 46 | static void txdscr_init() |
andrewboyson | 59:e0e556c8bd46 | 47 | { |
andrewboyson | 59:e0e556c8bd46 | 48 | int i; |
andrewboyson | 59:e0e556c8bd46 | 49 | |
andrewboyson | 59:e0e556c8bd46 | 50 | for(i = 0; i < NUM_TX_FRAMES; i++) |
andrewboyson | 59:e0e556c8bd46 | 51 | { |
andrewboyson | 59:e0e556c8bd46 | 52 | t_desc[i].Packet = (uint32_t)&t_buff[i]; |
andrewboyson | 59:e0e556c8bd46 | 53 | t_desc[i].Ctrl = 0; |
andrewboyson | 59:e0e556c8bd46 | 54 | t_stat[i].Info = 0; |
andrewboyson | 59:e0e556c8bd46 | 55 | } |
andrewboyson | 59:e0e556c8bd46 | 56 | |
andrewboyson | 59:e0e556c8bd46 | 57 | LPC_EMAC->TxDescriptor = (uint32_t)t_desc; /* Set EMAC Transmit Descriptor Registers. */ |
andrewboyson | 59:e0e556c8bd46 | 58 | LPC_EMAC->TxStatus = (uint32_t)t_stat; |
andrewboyson | 59:e0e556c8bd46 | 59 | LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAMES - 1; |
andrewboyson | 59:e0e556c8bd46 | 60 | |
andrewboyson | 59:e0e556c8bd46 | 61 | LPC_EMAC->TxProduceIndex = 0; /* Tx Descriptors Point to 0 */ |
andrewboyson | 59:e0e556c8bd46 | 62 | } |
andrewboyson | 59:e0e556c8bd46 | 63 | |
andrewboyson | 59:e0e556c8bd46 | 64 | static void rxdscr_init() |
andrewboyson | 59:e0e556c8bd46 | 65 | { |
andrewboyson | 59:e0e556c8bd46 | 66 | int i; |
andrewboyson | 59:e0e556c8bd46 | 67 | |
andrewboyson | 59:e0e556c8bd46 | 68 | for(i = 0; i < NUM_RX_FRAMES; i++) |
andrewboyson | 59:e0e556c8bd46 | 69 | { |
andrewboyson | 59:e0e556c8bd46 | 70 | r_desc[i].Packet = (uint32_t)&r_buff[i]; |
andrewboyson | 59:e0e556c8bd46 | 71 | r_desc[i].Ctrl = RCTRL_INT | (ETH_FRAME_LEN-1); |
andrewboyson | 59:e0e556c8bd46 | 72 | r_stat[i].Info = 0; |
andrewboyson | 59:e0e556c8bd46 | 73 | r_stat[i].HashCRC = 0; |
andrewboyson | 59:e0e556c8bd46 | 74 | } |
andrewboyson | 59:e0e556c8bd46 | 75 | |
andrewboyson | 59:e0e556c8bd46 | 76 | LPC_EMAC->RxDescriptor = (uint32_t)r_desc; /* Set EMAC Receive Descriptor Registers. */ |
andrewboyson | 59:e0e556c8bd46 | 77 | LPC_EMAC->RxStatus = (uint32_t)r_stat; //Must be aligned on an 8 byte boundary |
andrewboyson | 59:e0e556c8bd46 | 78 | LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAMES - 1; |
andrewboyson | 59:e0e556c8bd46 | 79 | |
andrewboyson | 59:e0e556c8bd46 | 80 | LPC_EMAC->RxConsumeIndex = 0; /* Rx Descriptors Point to 0 */ |
andrewboyson | 59:e0e556c8bd46 | 81 | } |
andrewboyson | 59:e0e556c8bd46 | 82 | static int phy_write(unsigned int PhyReg, unsigned short Data) |
andrewboyson | 59:e0e556c8bd46 | 83 | { |
andrewboyson | 59:e0e556c8bd46 | 84 | unsigned int timeOut; |
andrewboyson | 59:e0e556c8bd46 | 85 | |
andrewboyson | 59:e0e556c8bd46 | 86 | LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; |
andrewboyson | 59:e0e556c8bd46 | 87 | LPC_EMAC->MWTD = Data; |
andrewboyson | 59:e0e556c8bd46 | 88 | |
andrewboyson | 59:e0e556c8bd46 | 89 | // Wait until operation completed |
andrewboyson | 59:e0e556c8bd46 | 90 | for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) |
andrewboyson | 59:e0e556c8bd46 | 91 | { |
andrewboyson | 59:e0e556c8bd46 | 92 | if((LPC_EMAC->MIND & MIND_BUSY) == 0) return 0; |
andrewboyson | 59:e0e556c8bd46 | 93 | } |
andrewboyson | 59:e0e556c8bd46 | 94 | |
andrewboyson | 59:e0e556c8bd46 | 95 | //Timed out |
andrewboyson | 59:e0e556c8bd46 | 96 | return -1; |
andrewboyson | 59:e0e556c8bd46 | 97 | } |
andrewboyson | 59:e0e556c8bd46 | 98 | |
andrewboyson | 59:e0e556c8bd46 | 99 | static int phy_read(unsigned int PhyReg) |
andrewboyson | 59:e0e556c8bd46 | 100 | { |
andrewboyson | 59:e0e556c8bd46 | 101 | unsigned int timeOut; |
andrewboyson | 59:e0e556c8bd46 | 102 | |
andrewboyson | 59:e0e556c8bd46 | 103 | LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; |
andrewboyson | 59:e0e556c8bd46 | 104 | LPC_EMAC->MCMD = MCMD_READ; |
andrewboyson | 59:e0e556c8bd46 | 105 | |
andrewboyson | 59:e0e556c8bd46 | 106 | // Wait until operation completed |
andrewboyson | 59:e0e556c8bd46 | 107 | for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) |
andrewboyson | 59:e0e556c8bd46 | 108 | { |
andrewboyson | 59:e0e556c8bd46 | 109 | if((LPC_EMAC->MIND & MIND_BUSY) == 0) |
andrewboyson | 59:e0e556c8bd46 | 110 | { |
andrewboyson | 59:e0e556c8bd46 | 111 | LPC_EMAC->MCMD = 0; |
andrewboyson | 59:e0e556c8bd46 | 112 | return LPC_EMAC->MRDD; // Return a 16-bit value. |
andrewboyson | 59:e0e556c8bd46 | 113 | } |
andrewboyson | 59:e0e556c8bd46 | 114 | } |
andrewboyson | 59:e0e556c8bd46 | 115 | return -1; |
andrewboyson | 59:e0e556c8bd46 | 116 | } |
andrewboyson | 59:e0e556c8bd46 | 117 | |
andrewboyson | 59:e0e556c8bd46 | 118 | void NicLinkAddress(char *mac) |
andrewboyson | 59:e0e556c8bd46 | 119 | { |
andrewboyson | 59:e0e556c8bd46 | 120 | mbed_mac_address(mac); |
andrewboyson | 59:e0e556c8bd46 | 121 | } |
andrewboyson | 59:e0e556c8bd46 | 122 | |
andrewboyson | 59:e0e556c8bd46 | 123 | void NicLinkSetSpeedDuplex(int speed, int duplex) |
andrewboyson | 59:e0e556c8bd46 | 124 | { |
andrewboyson | 59:e0e556c8bd46 | 125 | unsigned short phy_data; |
andrewboyson | 59:e0e556c8bd46 | 126 | int tout; |
andrewboyson | 59:e0e556c8bd46 | 127 | |
andrewboyson | 59:e0e556c8bd46 | 128 | if((speed < 0) || (speed > 1)) phy_data = PHY_AUTO_NEG; |
andrewboyson | 59:e0e556c8bd46 | 129 | else phy_data = (((unsigned short) speed << 13) | ((unsigned short) duplex << 8)); |
andrewboyson | 59:e0e556c8bd46 | 130 | |
andrewboyson | 59:e0e556c8bd46 | 131 | phy_write(PHY_REG_BMCR, phy_data); |
andrewboyson | 59:e0e556c8bd46 | 132 | |
andrewboyson | 59:e0e556c8bd46 | 133 | for(tout = 100; tout; tout--) __NOP(); /* A short delay */ |
andrewboyson | 59:e0e556c8bd46 | 134 | |
andrewboyson | 59:e0e556c8bd46 | 135 | phy_data = phy_read(PHY_REG_STS); |
andrewboyson | 59:e0e556c8bd46 | 136 | |
andrewboyson | 59:e0e556c8bd46 | 137 | if(phy_data & PHY_STS_DUPLEX) |
andrewboyson | 59:e0e556c8bd46 | 138 | { |
andrewboyson | 59:e0e556c8bd46 | 139 | LPC_EMAC->MAC2 |= MAC2_FULL_DUP; |
andrewboyson | 59:e0e556c8bd46 | 140 | LPC_EMAC->Command |= CR_FULL_DUP; |
andrewboyson | 59:e0e556c8bd46 | 141 | LPC_EMAC->IPGT = IPGT_FULL_DUP; |
andrewboyson | 59:e0e556c8bd46 | 142 | } |
andrewboyson | 59:e0e556c8bd46 | 143 | else |
andrewboyson | 59:e0e556c8bd46 | 144 | { |
andrewboyson | 59:e0e556c8bd46 | 145 | LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP; |
andrewboyson | 59:e0e556c8bd46 | 146 | LPC_EMAC->Command &= ~CR_FULL_DUP; |
andrewboyson | 59:e0e556c8bd46 | 147 | LPC_EMAC->IPGT = IPGT_HALF_DUP; |
andrewboyson | 59:e0e556c8bd46 | 148 | } |
andrewboyson | 59:e0e556c8bd46 | 149 | |
andrewboyson | 59:e0e556c8bd46 | 150 | if(phy_data & PHY_STS_SPEED) |
andrewboyson | 59:e0e556c8bd46 | 151 | { |
andrewboyson | 59:e0e556c8bd46 | 152 | LPC_EMAC->SUPP &= ~SUPP_SPEED; |
andrewboyson | 59:e0e556c8bd46 | 153 | } |
andrewboyson | 59:e0e556c8bd46 | 154 | else |
andrewboyson | 59:e0e556c8bd46 | 155 | { |
andrewboyson | 59:e0e556c8bd46 | 156 | LPC_EMAC->SUPP |= SUPP_SPEED; |
andrewboyson | 59:e0e556c8bd46 | 157 | } |
andrewboyson | 59:e0e556c8bd46 | 158 | } |
andrewboyson | 59:e0e556c8bd46 | 159 | |
andrewboyson | 59:e0e556c8bd46 | 160 | int NicLinkIsUp(void) |
andrewboyson | 59:e0e556c8bd46 | 161 | { |
andrewboyson | 59:e0e556c8bd46 | 162 | return (phy_read(PHY_REG_STS) & PHY_STS_LINK); |
andrewboyson | 59:e0e556c8bd46 | 163 | } |
andrewboyson | 59:e0e556c8bd46 | 164 | static int phy_reset() |
andrewboyson | 59:e0e556c8bd46 | 165 | { |
andrewboyson | 59:e0e556c8bd46 | 166 | int regv, tout; |
andrewboyson | 59:e0e556c8bd46 | 167 | |
andrewboyson | 59:e0e556c8bd46 | 168 | // perform PHY reset |
andrewboyson | 59:e0e556c8bd46 | 169 | phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); |
andrewboyson | 59:e0e556c8bd46 | 170 | |
andrewboyson | 59:e0e556c8bd46 | 171 | // Wait for hardware reset to end. |
andrewboyson | 59:e0e556c8bd46 | 172 | for(tout = 0x20000; ; tout--) |
andrewboyson | 59:e0e556c8bd46 | 173 | { |
andrewboyson | 59:e0e556c8bd46 | 174 | regv = phy_read(PHY_REG_BMCR); |
andrewboyson | 59:e0e556c8bd46 | 175 | if(regv < 0 || tout == 0) return -1; // Error |
andrewboyson | 59:e0e556c8bd46 | 176 | if(!(regv & PHY_BMCR_RESET)) break; // Reset complete. |
andrewboyson | 59:e0e556c8bd46 | 177 | } |
andrewboyson | 59:e0e556c8bd46 | 178 | uint32_t phy_id = (phy_read(PHY_REG_IDR1) << 16); |
andrewboyson | 59:e0e556c8bd46 | 179 | phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0); |
andrewboyson | 59:e0e556c8bd46 | 180 | |
andrewboyson | 59:e0e556c8bd46 | 181 | //Check is the right PHY |
andrewboyson | 59:e0e556c8bd46 | 182 | if (phy_id != DP83848C_ID) |
andrewboyson | 59:e0e556c8bd46 | 183 | { |
andrewboyson | 59:e0e556c8bd46 | 184 | error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id); |
andrewboyson | 59:e0e556c8bd46 | 185 | return -1; |
andrewboyson | 59:e0e556c8bd46 | 186 | } |
andrewboyson | 59:e0e556c8bd46 | 187 | return 0; |
andrewboyson | 59:e0e556c8bd46 | 188 | } |
andrewboyson | 59:e0e556c8bd46 | 189 | int NicInit() |
andrewboyson | 59:e0e556c8bd46 | 190 | { |
andrewboyson | 59:e0e556c8bd46 | 191 | int tout; |
andrewboyson | 59:e0e556c8bd46 | 192 | char mac[6]; |
andrewboyson | 59:e0e556c8bd46 | 193 | unsigned int clock = 10; //96,000,000 |
andrewboyson | 59:e0e556c8bd46 | 194 | |
andrewboyson | 59:e0e556c8bd46 | 195 | // Power Up the EMAC controller. |
andrewboyson | 59:e0e556c8bd46 | 196 | LPC_SC->PCONP |= 0x40000000; |
andrewboyson | 59:e0e556c8bd46 | 197 | |
andrewboyson | 59:e0e556c8bd46 | 198 | // Enable P1 Ethernet Pins. |
andrewboyson | 59:e0e556c8bd46 | 199 | LPC_PINCON->PINSEL2 = 0x50150105; |
andrewboyson | 59:e0e556c8bd46 | 200 | LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005; |
andrewboyson | 59:e0e556c8bd46 | 201 | |
andrewboyson | 59:e0e556c8bd46 | 202 | // Reset all EMAC internal modules. |
andrewboyson | 59:e0e556c8bd46 | 203 | LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; |
andrewboyson | 59:e0e556c8bd46 | 204 | LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; |
andrewboyson | 59:e0e556c8bd46 | 205 | |
andrewboyson | 59:e0e556c8bd46 | 206 | // A short delay after reset. |
andrewboyson | 59:e0e556c8bd46 | 207 | for(tout = 100; tout; tout--) __NOP(); |
andrewboyson | 59:e0e556c8bd46 | 208 | |
andrewboyson | 59:e0e556c8bd46 | 209 | // Initialize MAC control registers. |
andrewboyson | 59:e0e556c8bd46 | 210 | LPC_EMAC->MAC1 = MAC1_PASS_ALL; |
andrewboyson | 59:e0e556c8bd46 | 211 | LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; |
andrewboyson | 59:e0e556c8bd46 | 212 | LPC_EMAC->MAXF = ETH_FRAME_LEN; |
andrewboyson | 59:e0e556c8bd46 | 213 | LPC_EMAC->CLRT = CLRT_DEF; |
andrewboyson | 59:e0e556c8bd46 | 214 | LPC_EMAC->IPGR = IPGR_DEF; |
andrewboyson | 59:e0e556c8bd46 | 215 | |
andrewboyson | 59:e0e556c8bd46 | 216 | // Enable Reduced MII interface. |
andrewboyson | 59:e0e556c8bd46 | 217 | LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; |
andrewboyson | 59:e0e556c8bd46 | 218 | |
andrewboyson | 59:e0e556c8bd46 | 219 | // Set clock and reset |
andrewboyson | 59:e0e556c8bd46 | 220 | LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; |
andrewboyson | 59:e0e556c8bd46 | 221 | LPC_EMAC->MCFG |= MCFG_RES_MII; |
andrewboyson | 59:e0e556c8bd46 | 222 | |
andrewboyson | 59:e0e556c8bd46 | 223 | // A short delay after reset |
andrewboyson | 59:e0e556c8bd46 | 224 | for(tout = 100; tout; tout--) __NOP(); |
andrewboyson | 59:e0e556c8bd46 | 225 | |
andrewboyson | 59:e0e556c8bd46 | 226 | // Set clock |
andrewboyson | 59:e0e556c8bd46 | 227 | LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; |
andrewboyson | 59:e0e556c8bd46 | 228 | LPC_EMAC->MCMD = 0; |
andrewboyson | 59:e0e556c8bd46 | 229 | |
andrewboyson | 59:e0e556c8bd46 | 230 | // Reset Reduced MII Logic. |
andrewboyson | 59:e0e556c8bd46 | 231 | LPC_EMAC->SUPP = SUPP_RES_RMII; |
andrewboyson | 59:e0e556c8bd46 | 232 | |
andrewboyson | 59:e0e556c8bd46 | 233 | // A short delay |
andrewboyson | 59:e0e556c8bd46 | 234 | for (tout = 100; tout; tout--) __NOP(); |
andrewboyson | 59:e0e556c8bd46 | 235 | |
andrewboyson | 59:e0e556c8bd46 | 236 | LPC_EMAC->SUPP = 0; |
andrewboyson | 59:e0e556c8bd46 | 237 | |
andrewboyson | 59:e0e556c8bd46 | 238 | //Reset the PHY |
andrewboyson | 59:e0e556c8bd46 | 239 | if (phy_reset()) return -1; |
andrewboyson | 59:e0e556c8bd46 | 240 | |
andrewboyson | 59:e0e556c8bd46 | 241 | //Set the link to auto negotiate |
andrewboyson | 59:e0e556c8bd46 | 242 | NicLinkSetSpeedDuplex(-1, 0); |
andrewboyson | 59:e0e556c8bd46 | 243 | |
andrewboyson | 59:e0e556c8bd46 | 244 | // Set the Ethernet MAC Address registers |
andrewboyson | 59:e0e556c8bd46 | 245 | NicLinkAddress(mac); |
andrewboyson | 59:e0e556c8bd46 | 246 | LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4]; |
andrewboyson | 59:e0e556c8bd46 | 247 | LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2]; |
andrewboyson | 59:e0e556c8bd46 | 248 | LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0]; |
andrewboyson | 59:e0e556c8bd46 | 249 | |
andrewboyson | 59:e0e556c8bd46 | 250 | //Initialise DMA descriptors |
andrewboyson | 59:e0e556c8bd46 | 251 | txdscr_init(); |
andrewboyson | 59:e0e556c8bd46 | 252 | rxdscr_init(); |
andrewboyson | 59:e0e556c8bd46 | 253 | |
andrewboyson | 59:e0e556c8bd46 | 254 | // Set filter |
andrewboyson | 59:e0e556c8bd46 | 255 | LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; |
andrewboyson | 59:e0e556c8bd46 | 256 | |
andrewboyson | 59:e0e556c8bd46 | 257 | // Enable and clear EMAC interrupts |
andrewboyson | 59:e0e556c8bd46 | 258 | //LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; |
andrewboyson | 59:e0e556c8bd46 | 259 | // Disable and clear EMAC interrupts |
andrewboyson | 59:e0e556c8bd46 | 260 | LPC_EMAC->IntEnable = 0; |
andrewboyson | 59:e0e556c8bd46 | 261 | LPC_EMAC->IntClear = 0xFFFF; |
andrewboyson | 59:e0e556c8bd46 | 262 | |
andrewboyson | 59:e0e556c8bd46 | 263 | //Enable receive and transmit |
andrewboyson | 59:e0e556c8bd46 | 264 | LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); |
andrewboyson | 59:e0e556c8bd46 | 265 | LPC_EMAC->MAC1 |= MAC1_REC_EN; |
andrewboyson | 59:e0e556c8bd46 | 266 | |
andrewboyson | 59:e0e556c8bd46 | 267 | //Return success |
andrewboyson | 59:e0e556c8bd46 | 268 | return 0; |
andrewboyson | 59:e0e556c8bd46 | 269 | } |
andrewboyson | 59:e0e556c8bd46 | 270 | |
andrewboyson | 59:e0e556c8bd46 | 271 | void NicFree() { |
andrewboyson | 59:e0e556c8bd46 | 272 | LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE); |
andrewboyson | 59:e0e556c8bd46 | 273 | LPC_EMAC->IntClear = 0xFFFF; |
andrewboyson | 59:e0e556c8bd46 | 274 | |
andrewboyson | 59:e0e556c8bd46 | 275 | LPC_SC->PCONP &= ~0x40000000; /* Power down the EMAC controller. */ |
andrewboyson | 59:e0e556c8bd46 | 276 | |
andrewboyson | 59:e0e556c8bd46 | 277 | LPC_PINCON->PINSEL2 &= ~0x50150105; /* Disable P1 ethernet pins. */ |
andrewboyson | 59:e0e556c8bd46 | 278 | LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000000; |
andrewboyson | 59:e0e556c8bd46 | 279 | } |