LPC1768 Mini-DK EasyWeb application with SPI TFT output. Started from EasyWebCR and modified for DM9161 PHY support.

Dependencies:   Mini-DK mbed

This is a very basic EasyWeb application.

No error checking is performed during initialisation.

Information

If the webpage is not reachable or the 'Webserver running' message does not appear, press the reset button on the Mini-DK and wait until the message 'Webserver running' appears.
This happens sometimes when powering up the Mini-DK because the DM9161 reset pin is NOT controlled by the LPC1768, it is directly connected to the reset button.

IP adress/mask/gateway in tcpip.h : 192.168.0.200 / 255.255.255.0 / 192.168.0.1

MAC address in ethmac.h : 6-5-4-3-2-1

Committer:
frankvnk
Date:
Tue Jan 15 06:43:51 2013 +0000
Revision:
8:4c3db9231e3f
Parent:
3:342aa2cf54e8
DM9161_BMSR - bit 13 define modified

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 }