Frank Vannieuwkerke / Mbed 2 deprecated LPC1768_Mini-DK_EasyWeb_DM9161

Dependencies:   Mini-DK mbed

Committer:
frankvnk
Date:
Sat Dec 22 17:03:00 2012 +0000
Revision:
1:d13a0eb82022
Parent:
0:636056c0b5e1
ethmac.c - EMAC_clkdiv[] had too few dividers for high cpu clock.
; EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
; replaced with
; EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64 };
;
;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:636056c0b5e1 1 /******************************************************************
frankvnk 0:636056c0b5e1 2 ***** *****
frankvnk 0:636056c0b5e1 3 ***** Name: ethmac.c *****
frankvnk 0:636056c0b5e1 4 ***** Ver.: 1.0 *****
frankvnk 0:636056c0b5e1 5 ***** Date: 17/12/2012 *****
frankvnk 0:636056c0b5e1 6 ***** Auth: Frank Vannieuwkerke *****
frankvnk 0:636056c0b5e1 7 ***** Func: ethernet packet-driver for use with LAN- *****
frankvnk 0:636056c0b5e1 8 ***** controller DM9161 *****
frankvnk 0:636056c0b5e1 9 ***** Rewrite from Andreas Dannenberg *****
frankvnk 0:636056c0b5e1 10 ***** HTWK Leipzig *****
frankvnk 0:636056c0b5e1 11 ***** university of applied sciences *****
frankvnk 0:636056c0b5e1 12 ***** Germany *****
frankvnk 0:636056c0b5e1 13 ***** adannenb@et.htwk-leipzig.de *****
frankvnk 0:636056c0b5e1 14 ***** *****
frankvnk 0:636056c0b5e1 15 ******************************************************************/
frankvnk 0:636056c0b5e1 16 /*
frankvnk 0:636056c0b5e1 17 NOTES:
frankvnk 0:636056c0b5e1 18 ------
frankvnk 0:636056c0b5e1 19 - WriteToPHY and ReadFromPHY don't signal error status.
frankvnk 0:636056c0b5e1 20 (ReadFromPHY only returns value on success)
frankvnk 0:636056c0b5e1 21 Possible improvement : if status = OK - return(0) for Write
frankvnk 0:636056c0b5e1 22 if status = NOK - return(-1) for Write and Read
frankvnk 0:636056c0b5e1 23 */
frankvnk 0:636056c0b5e1 24 #include "mbed.h"
frankvnk 0:636056c0b5e1 25 #include "ethmac.h"
frankvnk 0:636056c0b5e1 26 #include "tcpip.h"
frankvnk 0:636056c0b5e1 27
frankvnk 0:636056c0b5e1 28 /* MII Mgmt Configuration register - Clock divider setting */
frankvnk 1:d13a0eb82022 29 const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64 };
frankvnk 0:636056c0b5e1 30
frankvnk 0:636056c0b5e1 31 // static pointers for receive and transmit
frankvnk 0:636056c0b5e1 32 static unsigned short *rxptr;
frankvnk 0:636056c0b5e1 33 static unsigned short *txptr;
frankvnk 0:636056c0b5e1 34
frankvnk 0:636056c0b5e1 35 // write to external ethernet PHY chip
frankvnk 0:636056c0b5e1 36 void WriteToPHY (int reg, int writeval)
frankvnk 0:636056c0b5e1 37 {
frankvnk 0:636056c0b5e1 38 unsigned int loop;
frankvnk 0:636056c0b5e1 39 // Set up address to access in MII Mgmt Address Register
frankvnk 0:636056c0b5e1 40 LPC_EMAC->MADR = DM9161_DEF_ADR | reg;
frankvnk 0:636056c0b5e1 41 // Write value into MII Mgmt Write Data Register
frankvnk 0:636056c0b5e1 42 LPC_EMAC->MWTD = writeval;
frankvnk 0:636056c0b5e1 43 // Loop whilst write to PHY completes
frankvnk 0:636056c0b5e1 44 for (loop = 0; loop < MII_WR_TOUT; loop++) {
frankvnk 0:636056c0b5e1 45 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { break; }
frankvnk 0:636056c0b5e1 46 }
frankvnk 0:636056c0b5e1 47 }
frankvnk 0:636056c0b5e1 48
frankvnk 0:636056c0b5e1 49 // read from external ethernet PHY chip
frankvnk 0:636056c0b5e1 50 unsigned short ReadFromPHY (unsigned char reg)
frankvnk 0:636056c0b5e1 51 {
frankvnk 0:636056c0b5e1 52 unsigned int loop;
frankvnk 0:636056c0b5e1 53 // Set up address to access in MII Mgmt Address Register
frankvnk 0:636056c0b5e1 54 LPC_EMAC->MADR = DM9161_DEF_ADR | reg;
frankvnk 0:636056c0b5e1 55 // Trigger a PHY read via MII Mgmt Command Register
frankvnk 0:636056c0b5e1 56 LPC_EMAC->MCMD = MCMD_READ;
frankvnk 0:636056c0b5e1 57 // Loop whilst read from PHY completes
frankvnk 0:636056c0b5e1 58 for (loop = 0; loop < MII_RD_TOUT; loop++) {
frankvnk 0:636056c0b5e1 59 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) { break; }
frankvnk 0:636056c0b5e1 60 }
frankvnk 0:636056c0b5e1 61 LPC_EMAC->MCMD = 0; // Cancel read
frankvnk 0:636056c0b5e1 62 // Returned value is in MII Mgmt Read Data Register
frankvnk 0:636056c0b5e1 63 return (LPC_EMAC->MRDD);
frankvnk 0:636056c0b5e1 64 }
frankvnk 0:636056c0b5e1 65
frankvnk 0:636056c0b5e1 66 void Init_EthMAC(void)
frankvnk 0:636056c0b5e1 67 {
frankvnk 0:636056c0b5e1 68 unsigned int loop, value, phyid1, phyid2;
frankvnk 0:636056c0b5e1 69
frankvnk 0:636056c0b5e1 70 unsigned phy_in_use = 0;
frankvnk 0:636056c0b5e1 71
frankvnk 0:636056c0b5e1 72 // Set Ethernet power/clock control bit
frankvnk 0:636056c0b5e1 73 LPC_SC->PCONP |= PCENET;
frankvnk 0:636056c0b5e1 74
frankvnk 0:636056c0b5e1 75 //Enable Ethernet pins through PINSEL registers
frankvnk 0:636056c0b5e1 76 LPC_PINCON->PINSEL2 = ENET_PINSEL2_CONFIG;
frankvnk 0:636056c0b5e1 77 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~(ENET_PINSEL3_MASK)) | ENET_PINSEL3_CONFIG;
frankvnk 0:636056c0b5e1 78
frankvnk 0:636056c0b5e1 79 // Set up MAC Configuration Register 1
frankvnk 0:636056c0b5e1 80 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
frankvnk 0:636056c0b5e1 81 MAC1_RES_MCS_RX |MAC1_SIM_RES | MAC1_SOFT_RES;
frankvnk 0:636056c0b5e1 82
frankvnk 0:636056c0b5e1 83 // Set up MAC Command Register
frankvnk 0:636056c0b5e1 84 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
frankvnk 0:636056c0b5e1 85
frankvnk 0:636056c0b5e1 86 // Short delay
frankvnk 0:636056c0b5e1 87 for (loop = 100; loop; loop--);
frankvnk 0:636056c0b5e1 88
frankvnk 0:636056c0b5e1 89 // Set up MAC Configuration Register 1 to pass all receive frames
frankvnk 0:636056c0b5e1 90 LPC_EMAC->MAC1 = MAC1_PASS_ALL;
frankvnk 0:636056c0b5e1 91 // Set up MAC Configuration Register 2 to append CRC and pad out frames
frankvnk 0:636056c0b5e1 92 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
frankvnk 0:636056c0b5e1 93 // Set Ethernet Maximum Frame Register
frankvnk 0:636056c0b5e1 94 LPC_EMAC->MAXF = ETH_MAX_FLEN;
frankvnk 0:636056c0b5e1 95 // Set Collision Window / Retry Register
frankvnk 0:636056c0b5e1 96 LPC_EMAC->CLRT = CLRT_DEF;
frankvnk 0:636056c0b5e1 97 // Set Non Back-to-Back Inter-Packet-Gap Register
frankvnk 0:636056c0b5e1 98 LPC_EMAC->IPGR = IPGR_DEF;
frankvnk 0:636056c0b5e1 99
frankvnk 0:636056c0b5e1 100 // Find the clock closest to desired target clock
frankvnk 0:636056c0b5e1 101 value = SystemCoreClock / MCFG_MII_MAXCLK;
frankvnk 0:636056c0b5e1 102 for (loop = 0; loop < sizeof (EMAC_clkdiv); loop++)
frankvnk 0:636056c0b5e1 103 {
frankvnk 0:636056c0b5e1 104 if (EMAC_clkdiv[loop] >= value) break;
frankvnk 0:636056c0b5e1 105 }
frankvnk 0:636056c0b5e1 106 loop++;
frankvnk 0:636056c0b5e1 107 // Write to MAC configuration register and reset
frankvnk 0:636056c0b5e1 108 LPC_EMAC->MCFG = MCFG_CLK_SEL(loop) | MCFG_RES_MII;
frankvnk 0:636056c0b5e1 109
frankvnk 0:636056c0b5e1 110 // release reset
frankvnk 0:636056c0b5e1 111 LPC_EMAC->MCFG &= ~(MCFG_RES_MII);
frankvnk 0:636056c0b5e1 112 LPC_EMAC->CLRT = CLRT_DEF;
frankvnk 0:636056c0b5e1 113 LPC_EMAC->IPGR = IPGR_DEF;
frankvnk 0:636056c0b5e1 114
frankvnk 0:636056c0b5e1 115 // Set MAC Command Register to enable Reduced MII interface
frankvnk 0:636056c0b5e1 116 // and prevent runt frames being filtered out
frankvnk 0:636056c0b5e1 117 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
frankvnk 0:636056c0b5e1 118 // LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
frankvnk 0:636056c0b5e1 119
frankvnk 0:636056c0b5e1 120 /* Reset Reduced MII Logic. */
frankvnk 0:636056c0b5e1 121 LPC_EMAC->SUPP = SUPP_RES_RMII;
frankvnk 0:636056c0b5e1 122 for (loop = 100; loop; loop--);
frankvnk 0:636056c0b5e1 123 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 124
frankvnk 0:636056c0b5e1 125 // Put DM9161 PHY into reset mode
frankvnk 0:636056c0b5e1 126 WriteToPHY (PHY_REG_BMCR, DM9161_RESET);
frankvnk 0:636056c0b5e1 127
frankvnk 0:636056c0b5e1 128 // Loop until hardware reset completes
frankvnk 0:636056c0b5e1 129 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 130 {
frankvnk 0:636056c0b5e1 131 value = ReadFromPHY (PHY_REG_BMCR);
frankvnk 0:636056c0b5e1 132 if (!(value & DM9161_RESET))
frankvnk 0:636056c0b5e1 133 {
frankvnk 0:636056c0b5e1 134 // Reset has completed
frankvnk 0:636056c0b5e1 135 break;
frankvnk 0:636056c0b5e1 136 }
frankvnk 0:636056c0b5e1 137 }
frankvnk 0:636056c0b5e1 138 // Just check this actually is a DM9161 PHY
frankvnk 0:636056c0b5e1 139 phyid1 = ReadFromPHY (PHY_REG_IDR1);
frankvnk 0:636056c0b5e1 140 phyid2 = ReadFromPHY (PHY_REG_IDR2);
frankvnk 0:636056c0b5e1 141
frankvnk 0:636056c0b5e1 142 if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == DM9161_ID)
frankvnk 0:636056c0b5e1 143 {
frankvnk 0:636056c0b5e1 144 phy_in_use = DM9161_ID;
frankvnk 0:636056c0b5e1 145 }
frankvnk 0:636056c0b5e1 146
frankvnk 0:636056c0b5e1 147 if (phy_in_use != 0)
frankvnk 0:636056c0b5e1 148 {
frankvnk 0:636056c0b5e1 149 // Safe to configure the PHY device
frankvnk 0:636056c0b5e1 150 // Set PHY to autonegotiation link speed
frankvnk 0:636056c0b5e1 151 // WriteToPHY (PHY_REG_BMCR, (DM9161_AUTONEG|DM9161_RESTART_AUTONEG));
frankvnk 0:636056c0b5e1 152 WriteToPHY (PHY_REG_BMCR, DM9161_AUTONEG | DM9161_SPEED_SELECT);
frankvnk 0:636056c0b5e1 153 // loop until autonegotiation completes
frankvnk 0:636056c0b5e1 154 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 155 {
frankvnk 0:636056c0b5e1 156 value = ReadFromPHY (PHY_REG_BMSR);
frankvnk 0:636056c0b5e1 157 if (value & DM9161_AUTONEG_COMP)
frankvnk 0:636056c0b5e1 158 {
frankvnk 0:636056c0b5e1 159 // Autonegotiation has completed
frankvnk 0:636056c0b5e1 160 break;
frankvnk 0:636056c0b5e1 161 }
frankvnk 0:636056c0b5e1 162 }
frankvnk 0:636056c0b5e1 163 }
frankvnk 0:636056c0b5e1 164
frankvnk 0:636056c0b5e1 165 // Now check the link status
frankvnk 0:636056c0b5e1 166 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 167 {
frankvnk 0:636056c0b5e1 168 value = ReadFromPHY (PHY_REG_DSCSR);
frankvnk 0:636056c0b5e1 169 if ((value & DM9161_100FDX)||(value & DM9161_100HDX)||(value & DM9161_10FDX)||(value & DM9161_10HDX))
frankvnk 0:636056c0b5e1 170 {
frankvnk 0:636056c0b5e1 171 // The link is on
frankvnk 0:636056c0b5e1 172 break;
frankvnk 0:636056c0b5e1 173 }
frankvnk 0:636056c0b5e1 174 }
frankvnk 0:636056c0b5e1 175
frankvnk 0:636056c0b5e1 176 // Now configure for 10/100Mbit and full/half duplex mode
frankvnk 0:636056c0b5e1 177 if (value & DM9161_100FDX)
frankvnk 0:636056c0b5e1 178 {
frankvnk 0:636056c0b5e1 179 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
frankvnk 0:636056c0b5e1 180 LPC_EMAC->Command |= CR_FULL_DUP;
frankvnk 0:636056c0b5e1 181 LPC_EMAC->IPGT = IPGT_FULL_DUP;
frankvnk 0:636056c0b5e1 182 LPC_EMAC->SUPP = SUPP_SPEED;
frankvnk 0:636056c0b5e1 183 WriteToPHY (PHY_REG_BMCR, PHY_FULLD_100M);
frankvnk 0:636056c0b5e1 184 }
frankvnk 0:636056c0b5e1 185 else if (value & DM9161_100HDX)
frankvnk 0:636056c0b5e1 186 {
frankvnk 0:636056c0b5e1 187 LPC_EMAC->IPGT = IPGT_HALF_DUP;
frankvnk 0:636056c0b5e1 188 LPC_EMAC->SUPP = SUPP_SPEED;
frankvnk 0:636056c0b5e1 189 WriteToPHY (PHY_REG_BMCR, PHY_HALFD_100M);
frankvnk 0:636056c0b5e1 190 }
frankvnk 0:636056c0b5e1 191 else if (value & DM9161_10FDX)
frankvnk 0:636056c0b5e1 192 {
frankvnk 0:636056c0b5e1 193 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
frankvnk 0:636056c0b5e1 194 LPC_EMAC->Command |= CR_FULL_DUP;
frankvnk 0:636056c0b5e1 195 LPC_EMAC->IPGT = IPGT_FULL_DUP;
frankvnk 0:636056c0b5e1 196 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 197 WriteToPHY (PHY_REG_BMCR, PHY_FULLD_10M);
frankvnk 0:636056c0b5e1 198 }
frankvnk 0:636056c0b5e1 199 else if (value & DM9161_10HDX)
frankvnk 0:636056c0b5e1 200 {
frankvnk 0:636056c0b5e1 201 LPC_EMAC->IPGT = IPGT_HALF_DUP;
frankvnk 0:636056c0b5e1 202 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 203 WriteToPHY (PHY_REG_BMCR, PHY_HALFD_10M);
frankvnk 0:636056c0b5e1 204 }
frankvnk 0:636056c0b5e1 205
frankvnk 0:636056c0b5e1 206 // Now set the Ethernet MAC Address registers
frankvnk 0:636056c0b5e1 207 // NOTE - MAC address must be unique on the network!
frankvnk 0:636056c0b5e1 208 LPC_EMAC->SA0 = (MYMAC_1 << 8) | MYMAC_2; // Station address 0 Reg
frankvnk 0:636056c0b5e1 209 LPC_EMAC->SA1 = (MYMAC_3 << 8) | MYMAC_4; // Station address 1 Reg
frankvnk 0:636056c0b5e1 210 LPC_EMAC->SA2 = (MYMAC_5 << 8) | MYMAC_6; // Station address 2 Reg
frankvnk 0:636056c0b5e1 211
frankvnk 0:636056c0b5e1 212
frankvnk 0:636056c0b5e1 213 // Now initialise the Rx descriptors
frankvnk 0:636056c0b5e1 214 for (loop = 0; loop < NUM_RX_FRAG; loop++)
frankvnk 0:636056c0b5e1 215 {
frankvnk 0:636056c0b5e1 216 RX_DESC_PACKET(loop) = RX_BUF(loop);
frankvnk 0:636056c0b5e1 217 RX_DESC_CTRL(loop) = RCTRL_INT | (ETH_FRAG_SIZE-1);
frankvnk 0:636056c0b5e1 218 RX_STAT_INFO(loop) = 0;
frankvnk 0:636056c0b5e1 219 RX_STAT_HASHCRC(loop) = 0;
frankvnk 0:636056c0b5e1 220 }
frankvnk 0:636056c0b5e1 221
frankvnk 0:636056c0b5e1 222 // Set up the Receive Descriptor Base address register
frankvnk 0:636056c0b5e1 223 LPC_EMAC->RxDescriptor = RX_DESC_BASE;
frankvnk 0:636056c0b5e1 224 // Set up the Receive Status Base address register
frankvnk 0:636056c0b5e1 225 LPC_EMAC->RxStatus = RX_STAT_BASE;
frankvnk 0:636056c0b5e1 226 // Setup the Receive Number of Descriptor register
frankvnk 0:636056c0b5e1 227 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
frankvnk 0:636056c0b5e1 228 // Set Receive Consume Index register to 0
frankvnk 0:636056c0b5e1 229 LPC_EMAC->RxConsumeIndex = 0;
frankvnk 0:636056c0b5e1 230
frankvnk 0:636056c0b5e1 231 // Now initialise the Tx descriptors
frankvnk 0:636056c0b5e1 232 for (loop = 0; loop < NUM_TX_FRAG; loop++)
frankvnk 0:636056c0b5e1 233 {
frankvnk 0:636056c0b5e1 234 TX_DESC_PACKET(loop) = TX_BUF(loop);
frankvnk 0:636056c0b5e1 235 TX_DESC_CTRL(loop) = 0;
frankvnk 0:636056c0b5e1 236 TX_STAT_INFO(loop) = 0;
frankvnk 0:636056c0b5e1 237 }
frankvnk 0:636056c0b5e1 238
frankvnk 0:636056c0b5e1 239 // Set up the Transmit Descriptor Base address register
frankvnk 0:636056c0b5e1 240 LPC_EMAC->TxDescriptor = TX_DESC_BASE;
frankvnk 0:636056c0b5e1 241 // Set up the Transmit Status Base address register
frankvnk 0:636056c0b5e1 242 LPC_EMAC->TxStatus = TX_STAT_BASE;
frankvnk 0:636056c0b5e1 243 // Setup the Transmit Number of Descriptor register
frankvnk 0:636056c0b5e1 244 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
frankvnk 0:636056c0b5e1 245 // Set Transmit Consume Index register to 0
frankvnk 0:636056c0b5e1 246 LPC_EMAC->TxProduceIndex = 0;
frankvnk 0:636056c0b5e1 247
frankvnk 0:636056c0b5e1 248 // Receive Broadcast and Perfect Match Packets
frankvnk 0:636056c0b5e1 249 LPC_EMAC->RxFilterCtrl = RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
frankvnk 0:636056c0b5e1 250
frankvnk 0:636056c0b5e1 251 // Enable interrupts MAC Module Control Interrupt Enable Register
frankvnk 0:636056c0b5e1 252 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
frankvnk 0:636056c0b5e1 253
frankvnk 0:636056c0b5e1 254 // Reset all ethernet interrupts in MAC module
frankvnk 0:636056c0b5e1 255 LPC_EMAC->IntClear = 0xFFFF;
frankvnk 0:636056c0b5e1 256
frankvnk 0:636056c0b5e1 257 // Finally enable receive and transmit mode in ethernet core
frankvnk 0:636056c0b5e1 258 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN);
frankvnk 0:636056c0b5e1 259 LPC_EMAC->MAC1 |= MAC1_REC_EN;
frankvnk 0:636056c0b5e1 260 }
frankvnk 0:636056c0b5e1 261
frankvnk 0:636056c0b5e1 262
frankvnk 0:636056c0b5e1 263 // writes a word in little-endian byte order to TX_BUFFER
frankvnk 0:636056c0b5e1 264 void WriteFrame_EthMAC(unsigned short Data)
frankvnk 0:636056c0b5e1 265 {
frankvnk 0:636056c0b5e1 266 *txptr++ = Data;
frankvnk 0:636056c0b5e1 267 }
frankvnk 0:636056c0b5e1 268
frankvnk 0:636056c0b5e1 269 // copies bytes from MCU-memory to frame port
frankvnk 0:636056c0b5e1 270 // NOTES: * an odd number of byte may only be transfered
frankvnk 0:636056c0b5e1 271 // if the frame is written to the end!
frankvnk 0:636056c0b5e1 272 // * MCU-memory MUST start at word-boundary
frankvnk 0:636056c0b5e1 273 void CopyToFrame_EthMAC(void *Source, unsigned int Size)
frankvnk 0:636056c0b5e1 274 {
frankvnk 0:636056c0b5e1 275 unsigned int index;
frankvnk 0:636056c0b5e1 276 unsigned short *pSource;
frankvnk 0:636056c0b5e1 277
frankvnk 0:636056c0b5e1 278 pSource = (unsigned short *)Source;
frankvnk 0:636056c0b5e1 279 Size = (Size + 1) & 0xFFFE; // round up Size to next even number
frankvnk 0:636056c0b5e1 280 while (Size > 0)
frankvnk 0:636056c0b5e1 281 {
frankvnk 0:636056c0b5e1 282 WriteFrame_EthMAC(*pSource++);
frankvnk 0:636056c0b5e1 283 Size -= 2;
frankvnk 0:636056c0b5e1 284 }
frankvnk 0:636056c0b5e1 285
frankvnk 0:636056c0b5e1 286 index = LPC_EMAC->TxProduceIndex;
frankvnk 0:636056c0b5e1 287 if (++index == NUM_TX_FRAG)
frankvnk 0:636056c0b5e1 288 index = 0;
frankvnk 0:636056c0b5e1 289 LPC_EMAC->TxProduceIndex = index;
frankvnk 0:636056c0b5e1 290 }
frankvnk 0:636056c0b5e1 291
frankvnk 0:636056c0b5e1 292 // reads a word in little-endian byte order from RX_BUFFER
frankvnk 0:636056c0b5e1 293 unsigned short ReadFrame_EthMAC(void)
frankvnk 0:636056c0b5e1 294 {
frankvnk 0:636056c0b5e1 295 return (*rxptr++);
frankvnk 0:636056c0b5e1 296 }
frankvnk 0:636056c0b5e1 297
frankvnk 0:636056c0b5e1 298
frankvnk 0:636056c0b5e1 299 // reads a word in big-endian byte order from RX_FRAME_PORT
frankvnk 0:636056c0b5e1 300 unsigned short ReadFrameBE_EthMAC(void)
frankvnk 0:636056c0b5e1 301 {
frankvnk 0:636056c0b5e1 302 unsigned short ReturnValue;
frankvnk 0:636056c0b5e1 303
frankvnk 0:636056c0b5e1 304 ReturnValue = SwapBytes (*rxptr++);
frankvnk 0:636056c0b5e1 305 return (ReturnValue);
frankvnk 0:636056c0b5e1 306 }
frankvnk 0:636056c0b5e1 307
frankvnk 0:636056c0b5e1 308 // copies bytes from frame port to MCU-memory
frankvnk 0:636056c0b5e1 309 // NOTES: * an odd number of byte may only be transfered
frankvnk 0:636056c0b5e1 310 // if the frame is read to the end!
frankvnk 0:636056c0b5e1 311 // * MCU-memory MUST start at word-boundary
frankvnk 0:636056c0b5e1 312 void CopyFromFrame_EthMAC(void *Dest, unsigned short Size)
frankvnk 0:636056c0b5e1 313 {
frankvnk 0:636056c0b5e1 314 unsigned short *pDest;
frankvnk 0:636056c0b5e1 315
frankvnk 0:636056c0b5e1 316 pDest = (unsigned short *)Dest;
frankvnk 0:636056c0b5e1 317 while (Size > 1)
frankvnk 0:636056c0b5e1 318 {
frankvnk 0:636056c0b5e1 319 *pDest++ = ReadFrame_EthMAC();
frankvnk 0:636056c0b5e1 320 Size -= 2;
frankvnk 0:636056c0b5e1 321 }
frankvnk 0:636056c0b5e1 322
frankvnk 0:636056c0b5e1 323 if (Size)
frankvnk 0:636056c0b5e1 324 { // check for leftover byte...
frankvnk 0:636056c0b5e1 325 *(unsigned char *)pDest = (char)ReadFrame_EthMAC(); // the LAN-Controller will return 0
frankvnk 0:636056c0b5e1 326 } // for the highbyte
frankvnk 0:636056c0b5e1 327 }
frankvnk 0:636056c0b5e1 328
frankvnk 0:636056c0b5e1 329
frankvnk 0:636056c0b5e1 330
frankvnk 0:636056c0b5e1 331 // does a dummy read on frame-I/O-port
frankvnk 0:636056c0b5e1 332 // NOTE: only an even number of bytes is read!
frankvnk 0:636056c0b5e1 333 void DummyReadFrame_EthMAC(unsigned short Size) // discards an EVEN number of bytes
frankvnk 0:636056c0b5e1 334 { // from RX-fifo
frankvnk 0:636056c0b5e1 335 while (Size > 1)
frankvnk 0:636056c0b5e1 336 {
frankvnk 0:636056c0b5e1 337 ReadFrame_EthMAC();
frankvnk 0:636056c0b5e1 338 Size -= 2;
frankvnk 0:636056c0b5e1 339 }
frankvnk 0:636056c0b5e1 340 }
frankvnk 0:636056c0b5e1 341
frankvnk 0:636056c0b5e1 342 // requests space in PHY on-chip memory for
frankvnk 0:636056c0b5e1 343 // storing an outgoing frame
frankvnk 0:636056c0b5e1 344 void RequestSend(unsigned short FrameSize)
frankvnk 0:636056c0b5e1 345 {
frankvnk 0:636056c0b5e1 346 unsigned int index;
frankvnk 0:636056c0b5e1 347 index = LPC_EMAC->TxProduceIndex;
frankvnk 0:636056c0b5e1 348 txptr = (unsigned short *)TX_DESC_PACKET(index);
frankvnk 0:636056c0b5e1 349 TX_DESC_CTRL(index) = FrameSize | TCTRL_LAST;
frankvnk 0:636056c0b5e1 350 }
frankvnk 0:636056c0b5e1 351
frankvnk 0:636056c0b5e1 352 // check if PHY is ready to accept the
frankvnk 0:636056c0b5e1 353 // frame we want to send
frankvnk 0:636056c0b5e1 354 unsigned int Rdy4Tx(void)
frankvnk 0:636056c0b5e1 355 {
frankvnk 0:636056c0b5e1 356 // One the LPC the ethernet controller transmits
frankvnk 0:636056c0b5e1 357 // much faster than the CPU can load its buffers
frankvnk 0:636056c0b5e1 358 // so will always be ready to accept frame
frankvnk 0:636056c0b5e1 359 return (1);
frankvnk 0:636056c0b5e1 360 }
frankvnk 0:636056c0b5e1 361
frankvnk 0:636056c0b5e1 362 // Reads length of received ethernet frame and checks
frankvnk 0:636056c0b5e1 363 // if destination address is a broadcast message or not.
frankvnk 0:636056c0b5e1 364 // Then returns the frame length
frankvnk 0:636056c0b5e1 365 unsigned short StartReadingFrame(void)
frankvnk 0:636056c0b5e1 366 {
frankvnk 0:636056c0b5e1 367 unsigned short ReceiveLength;
frankvnk 0:636056c0b5e1 368 unsigned int index;
frankvnk 0:636056c0b5e1 369
frankvnk 0:636056c0b5e1 370 index = LPC_EMAC->RxConsumeIndex;
frankvnk 0:636056c0b5e1 371 ReceiveLength = (RX_STAT_INFO(index) & RINFO_SIZE) - 3;
frankvnk 0:636056c0b5e1 372 rxptr = (unsigned short *)RX_DESC_PACKET(index);
frankvnk 0:636056c0b5e1 373 return(ReceiveLength);
frankvnk 0:636056c0b5e1 374 }
frankvnk 0:636056c0b5e1 375
frankvnk 0:636056c0b5e1 376 void StopReadingFrame(void)
frankvnk 0:636056c0b5e1 377 {
frankvnk 0:636056c0b5e1 378 unsigned int index;
frankvnk 0:636056c0b5e1 379 index = LPC_EMAC->RxConsumeIndex;
frankvnk 0:636056c0b5e1 380 if (++index == NUM_RX_FRAG) index = 0;
frankvnk 0:636056c0b5e1 381 LPC_EMAC->RxConsumeIndex = index;
frankvnk 0:636056c0b5e1 382 }
frankvnk 0:636056c0b5e1 383
frankvnk 0:636056c0b5e1 384 // check if frame has been received
frankvnk 0:636056c0b5e1 385 unsigned int CheckIfFrameReceived(void)
frankvnk 0:636056c0b5e1 386 {
frankvnk 0:636056c0b5e1 387 if (LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex)
frankvnk 0:636056c0b5e1 388 return(1); // Yes, packet received
frankvnk 0:636056c0b5e1 389 else
frankvnk 0:636056c0b5e1 390 return(0);
frankvnk 0:636056c0b5e1 391 }