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:
Fri Dec 21 15:41:54 2012 +0000
Revision:
0:636056c0b5e1
Child:
1:d13a0eb82022
First version - rewrite from EasyWebCR

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 0:636056c0b5e1 29 const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
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
frankvnk 0:636056c0b5e1 116 /* Enable Reduced MII interface. */
frankvnk 0:636056c0b5e1 117 /* REPLACED BY ABOVE CODE (find the clock...)
frankvnk 0:636056c0b5e1 118 LPC_EMAC->MCFG = MCFG_CLK_DIV64 | MCFG_RES_MII;
frankvnk 0:636056c0b5e1 119 for (loop = 100; loop; loop--);
frankvnk 0:636056c0b5e1 120 LPC_EMAC->MCFG = MCFG_CLK_DIV64;*/
frankvnk 0:636056c0b5e1 121
frankvnk 0:636056c0b5e1 122 // Set MAC Command Register to enable Reduced MII interface
frankvnk 0:636056c0b5e1 123 // and prevent runt frames being filtered out
frankvnk 0:636056c0b5e1 124 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
frankvnk 0:636056c0b5e1 125 // LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT;
frankvnk 0:636056c0b5e1 126
frankvnk 0:636056c0b5e1 127 /* Reset Reduced MII Logic. */
frankvnk 0:636056c0b5e1 128 LPC_EMAC->SUPP = SUPP_RES_RMII;
frankvnk 0:636056c0b5e1 129 for (loop = 100; loop; loop--);
frankvnk 0:636056c0b5e1 130 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 131
frankvnk 0:636056c0b5e1 132 // Put DM9161 PHY into reset mode
frankvnk 0:636056c0b5e1 133 WriteToPHY (PHY_REG_BMCR, DM9161_RESET);
frankvnk 0:636056c0b5e1 134
frankvnk 0:636056c0b5e1 135 // Loop until hardware reset completes
frankvnk 0:636056c0b5e1 136 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 137 {
frankvnk 0:636056c0b5e1 138 value = ReadFromPHY (PHY_REG_BMCR);
frankvnk 0:636056c0b5e1 139 if (!(value & DM9161_RESET))
frankvnk 0:636056c0b5e1 140 {
frankvnk 0:636056c0b5e1 141 // Reset has completed
frankvnk 0:636056c0b5e1 142 break;
frankvnk 0:636056c0b5e1 143 }
frankvnk 0:636056c0b5e1 144 }
frankvnk 0:636056c0b5e1 145 // Just check this actually is a DM9161 PHY
frankvnk 0:636056c0b5e1 146 phyid1 = ReadFromPHY (PHY_REG_IDR1);
frankvnk 0:636056c0b5e1 147 phyid2 = ReadFromPHY (PHY_REG_IDR2);
frankvnk 0:636056c0b5e1 148
frankvnk 0:636056c0b5e1 149 if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == DM9161_ID)
frankvnk 0:636056c0b5e1 150 {
frankvnk 0:636056c0b5e1 151 phy_in_use = DM9161_ID;
frankvnk 0:636056c0b5e1 152 }
frankvnk 0:636056c0b5e1 153
frankvnk 0:636056c0b5e1 154 if (phy_in_use != 0)
frankvnk 0:636056c0b5e1 155 {
frankvnk 0:636056c0b5e1 156 // Safe to configure the PHY device
frankvnk 0:636056c0b5e1 157 // Set PHY to autonegotiation link speed
frankvnk 0:636056c0b5e1 158 // WriteToPHY (PHY_REG_BMCR, (DM9161_AUTONEG|DM9161_RESTART_AUTONEG));
frankvnk 0:636056c0b5e1 159 WriteToPHY (PHY_REG_BMCR, DM9161_AUTONEG | DM9161_SPEED_SELECT);
frankvnk 0:636056c0b5e1 160 // loop until autonegotiation completes
frankvnk 0:636056c0b5e1 161 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 162 {
frankvnk 0:636056c0b5e1 163 value = ReadFromPHY (PHY_REG_BMSR);
frankvnk 0:636056c0b5e1 164 if (value & DM9161_AUTONEG_COMP)
frankvnk 0:636056c0b5e1 165 {
frankvnk 0:636056c0b5e1 166 // Autonegotiation has completed
frankvnk 0:636056c0b5e1 167 break;
frankvnk 0:636056c0b5e1 168 }
frankvnk 0:636056c0b5e1 169 }
frankvnk 0:636056c0b5e1 170 }
frankvnk 0:636056c0b5e1 171
frankvnk 0:636056c0b5e1 172 // Now check the link status
frankvnk 0:636056c0b5e1 173 for (loop = 0; loop < PHY_RESP_TOUT; loop++)
frankvnk 0:636056c0b5e1 174 {
frankvnk 0:636056c0b5e1 175 value = ReadFromPHY (PHY_REG_DSCSR);
frankvnk 0:636056c0b5e1 176 if ((value & DM9161_100FDX)||(value & DM9161_100HDX)||(value & DM9161_10FDX)||(value & DM9161_10HDX))
frankvnk 0:636056c0b5e1 177 {
frankvnk 0:636056c0b5e1 178 // The link is on
frankvnk 0:636056c0b5e1 179 break;
frankvnk 0:636056c0b5e1 180 }
frankvnk 0:636056c0b5e1 181 }
frankvnk 0:636056c0b5e1 182
frankvnk 0:636056c0b5e1 183 // Now configure for 10/100Mbit and full/half duplex mode
frankvnk 0:636056c0b5e1 184 if (value & DM9161_100FDX)
frankvnk 0:636056c0b5e1 185 {
frankvnk 0:636056c0b5e1 186 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
frankvnk 0:636056c0b5e1 187 LPC_EMAC->Command |= CR_FULL_DUP;
frankvnk 0:636056c0b5e1 188 LPC_EMAC->IPGT = IPGT_FULL_DUP;
frankvnk 0:636056c0b5e1 189 LPC_EMAC->SUPP = SUPP_SPEED;
frankvnk 0:636056c0b5e1 190 WriteToPHY (PHY_REG_BMCR, PHY_FULLD_100M);
frankvnk 0:636056c0b5e1 191 }
frankvnk 0:636056c0b5e1 192 else if (value & DM9161_100HDX)
frankvnk 0:636056c0b5e1 193 {
frankvnk 0:636056c0b5e1 194 LPC_EMAC->IPGT = IPGT_HALF_DUP;
frankvnk 0:636056c0b5e1 195 LPC_EMAC->SUPP = SUPP_SPEED;
frankvnk 0:636056c0b5e1 196 WriteToPHY (PHY_REG_BMCR, PHY_HALFD_100M);
frankvnk 0:636056c0b5e1 197 }
frankvnk 0:636056c0b5e1 198 else if (value & DM9161_10FDX)
frankvnk 0:636056c0b5e1 199 {
frankvnk 0:636056c0b5e1 200 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
frankvnk 0:636056c0b5e1 201 LPC_EMAC->Command |= CR_FULL_DUP;
frankvnk 0:636056c0b5e1 202 LPC_EMAC->IPGT = IPGT_FULL_DUP;
frankvnk 0:636056c0b5e1 203 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 204 WriteToPHY (PHY_REG_BMCR, PHY_FULLD_10M);
frankvnk 0:636056c0b5e1 205 }
frankvnk 0:636056c0b5e1 206 else if (value & DM9161_10HDX)
frankvnk 0:636056c0b5e1 207 {
frankvnk 0:636056c0b5e1 208 LPC_EMAC->IPGT = IPGT_HALF_DUP;
frankvnk 0:636056c0b5e1 209 LPC_EMAC->SUPP = 0;
frankvnk 0:636056c0b5e1 210 WriteToPHY (PHY_REG_BMCR, PHY_HALFD_10M);
frankvnk 0:636056c0b5e1 211 }
frankvnk 0:636056c0b5e1 212
frankvnk 0:636056c0b5e1 213 // Now set the Ethernet MAC Address registers
frankvnk 0:636056c0b5e1 214 // NOTE - MAC address must be unique on the network!
frankvnk 0:636056c0b5e1 215 LPC_EMAC->SA0 = (MYMAC_1 << 8) | MYMAC_2; // Station address 0 Reg
frankvnk 0:636056c0b5e1 216 LPC_EMAC->SA1 = (MYMAC_3 << 8) | MYMAC_4; // Station address 1 Reg
frankvnk 0:636056c0b5e1 217 LPC_EMAC->SA2 = (MYMAC_5 << 8) | MYMAC_6; // Station address 2 Reg
frankvnk 0:636056c0b5e1 218
frankvnk 0:636056c0b5e1 219
frankvnk 0:636056c0b5e1 220 // Now initialise the Rx descriptors
frankvnk 0:636056c0b5e1 221 for (loop = 0; loop < NUM_RX_FRAG; loop++)
frankvnk 0:636056c0b5e1 222 {
frankvnk 0:636056c0b5e1 223 RX_DESC_PACKET(loop) = RX_BUF(loop);
frankvnk 0:636056c0b5e1 224 RX_DESC_CTRL(loop) = RCTRL_INT | (ETH_FRAG_SIZE-1);
frankvnk 0:636056c0b5e1 225 RX_STAT_INFO(loop) = 0;
frankvnk 0:636056c0b5e1 226 RX_STAT_HASHCRC(loop) = 0;
frankvnk 0:636056c0b5e1 227 }
frankvnk 0:636056c0b5e1 228
frankvnk 0:636056c0b5e1 229 // Set up the Receive Descriptor Base address register
frankvnk 0:636056c0b5e1 230 LPC_EMAC->RxDescriptor = RX_DESC_BASE;
frankvnk 0:636056c0b5e1 231 // Set up the Receive Status Base address register
frankvnk 0:636056c0b5e1 232 LPC_EMAC->RxStatus = RX_STAT_BASE;
frankvnk 0:636056c0b5e1 233 // Setup the Receive Number of Descriptor register
frankvnk 0:636056c0b5e1 234 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
frankvnk 0:636056c0b5e1 235 // Set Receive Consume Index register to 0
frankvnk 0:636056c0b5e1 236 LPC_EMAC->RxConsumeIndex = 0;
frankvnk 0:636056c0b5e1 237
frankvnk 0:636056c0b5e1 238 // Now initialise the Tx descriptors
frankvnk 0:636056c0b5e1 239 for (loop = 0; loop < NUM_TX_FRAG; loop++)
frankvnk 0:636056c0b5e1 240 {
frankvnk 0:636056c0b5e1 241 TX_DESC_PACKET(loop) = TX_BUF(loop);
frankvnk 0:636056c0b5e1 242 TX_DESC_CTRL(loop) = 0;
frankvnk 0:636056c0b5e1 243 TX_STAT_INFO(loop) = 0;
frankvnk 0:636056c0b5e1 244 }
frankvnk 0:636056c0b5e1 245
frankvnk 0:636056c0b5e1 246 // Set up the Transmit Descriptor Base address register
frankvnk 0:636056c0b5e1 247 LPC_EMAC->TxDescriptor = TX_DESC_BASE;
frankvnk 0:636056c0b5e1 248 // Set up the Transmit Status Base address register
frankvnk 0:636056c0b5e1 249 LPC_EMAC->TxStatus = TX_STAT_BASE;
frankvnk 0:636056c0b5e1 250 // Setup the Transmit Number of Descriptor register
frankvnk 0:636056c0b5e1 251 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
frankvnk 0:636056c0b5e1 252 // Set Transmit Consume Index register to 0
frankvnk 0:636056c0b5e1 253 LPC_EMAC->TxProduceIndex = 0;
frankvnk 0:636056c0b5e1 254
frankvnk 0:636056c0b5e1 255 // Receive Broadcast and Perfect Match Packets
frankvnk 0:636056c0b5e1 256 LPC_EMAC->RxFilterCtrl = RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
frankvnk 0:636056c0b5e1 257
frankvnk 0:636056c0b5e1 258 // Enable interrupts MAC Module Control Interrupt Enable Register
frankvnk 0:636056c0b5e1 259 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE;
frankvnk 0:636056c0b5e1 260
frankvnk 0:636056c0b5e1 261 // Reset all ethernet interrupts in MAC module
frankvnk 0:636056c0b5e1 262 LPC_EMAC->IntClear = 0xFFFF;
frankvnk 0:636056c0b5e1 263
frankvnk 0:636056c0b5e1 264 // Finally enable receive and transmit mode in ethernet core
frankvnk 0:636056c0b5e1 265 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN);
frankvnk 0:636056c0b5e1 266 LPC_EMAC->MAC1 |= MAC1_REC_EN;
frankvnk 0:636056c0b5e1 267 }
frankvnk 0:636056c0b5e1 268
frankvnk 0:636056c0b5e1 269
frankvnk 0:636056c0b5e1 270 // writes a word in little-endian byte order to TX_BUFFER
frankvnk 0:636056c0b5e1 271 void WriteFrame_EthMAC(unsigned short Data)
frankvnk 0:636056c0b5e1 272 {
frankvnk 0:636056c0b5e1 273 *txptr++ = Data;
frankvnk 0:636056c0b5e1 274 }
frankvnk 0:636056c0b5e1 275
frankvnk 0:636056c0b5e1 276 // copies bytes from MCU-memory to frame port
frankvnk 0:636056c0b5e1 277 // NOTES: * an odd number of byte may only be transfered
frankvnk 0:636056c0b5e1 278 // if the frame is written to the end!
frankvnk 0:636056c0b5e1 279 // * MCU-memory MUST start at word-boundary
frankvnk 0:636056c0b5e1 280 void CopyToFrame_EthMAC(void *Source, unsigned int Size)
frankvnk 0:636056c0b5e1 281 {
frankvnk 0:636056c0b5e1 282 unsigned int index;
frankvnk 0:636056c0b5e1 283 unsigned short *pSource;
frankvnk 0:636056c0b5e1 284
frankvnk 0:636056c0b5e1 285 pSource = (unsigned short *)Source;
frankvnk 0:636056c0b5e1 286 Size = (Size + 1) & 0xFFFE; // round up Size to next even number
frankvnk 0:636056c0b5e1 287 while (Size > 0)
frankvnk 0:636056c0b5e1 288 {
frankvnk 0:636056c0b5e1 289 WriteFrame_EthMAC(*pSource++);
frankvnk 0:636056c0b5e1 290 Size -= 2;
frankvnk 0:636056c0b5e1 291 }
frankvnk 0:636056c0b5e1 292
frankvnk 0:636056c0b5e1 293 index = LPC_EMAC->TxProduceIndex;
frankvnk 0:636056c0b5e1 294 if (++index == NUM_TX_FRAG)
frankvnk 0:636056c0b5e1 295 index = 0;
frankvnk 0:636056c0b5e1 296 LPC_EMAC->TxProduceIndex = index;
frankvnk 0:636056c0b5e1 297 }
frankvnk 0:636056c0b5e1 298
frankvnk 0:636056c0b5e1 299 // reads a word in little-endian byte order from RX_BUFFER
frankvnk 0:636056c0b5e1 300 unsigned short ReadFrame_EthMAC(void)
frankvnk 0:636056c0b5e1 301 {
frankvnk 0:636056c0b5e1 302 return (*rxptr++);
frankvnk 0:636056c0b5e1 303 }
frankvnk 0:636056c0b5e1 304
frankvnk 0:636056c0b5e1 305
frankvnk 0:636056c0b5e1 306 // reads a word in big-endian byte order from RX_FRAME_PORT
frankvnk 0:636056c0b5e1 307 unsigned short ReadFrameBE_EthMAC(void)
frankvnk 0:636056c0b5e1 308 {
frankvnk 0:636056c0b5e1 309 unsigned short ReturnValue;
frankvnk 0:636056c0b5e1 310
frankvnk 0:636056c0b5e1 311 ReturnValue = SwapBytes (*rxptr++);
frankvnk 0:636056c0b5e1 312 return (ReturnValue);
frankvnk 0:636056c0b5e1 313 }
frankvnk 0:636056c0b5e1 314
frankvnk 0:636056c0b5e1 315 // copies bytes from frame port to MCU-memory
frankvnk 0:636056c0b5e1 316 // NOTES: * an odd number of byte may only be transfered
frankvnk 0:636056c0b5e1 317 // if the frame is read to the end!
frankvnk 0:636056c0b5e1 318 // * MCU-memory MUST start at word-boundary
frankvnk 0:636056c0b5e1 319 void CopyFromFrame_EthMAC(void *Dest, unsigned short Size)
frankvnk 0:636056c0b5e1 320 {
frankvnk 0:636056c0b5e1 321 unsigned short *pDest;
frankvnk 0:636056c0b5e1 322
frankvnk 0:636056c0b5e1 323 pDest = (unsigned short *)Dest;
frankvnk 0:636056c0b5e1 324 while (Size > 1)
frankvnk 0:636056c0b5e1 325 {
frankvnk 0:636056c0b5e1 326 *pDest++ = ReadFrame_EthMAC();
frankvnk 0:636056c0b5e1 327 Size -= 2;
frankvnk 0:636056c0b5e1 328 }
frankvnk 0:636056c0b5e1 329
frankvnk 0:636056c0b5e1 330 if (Size)
frankvnk 0:636056c0b5e1 331 { // check for leftover byte...
frankvnk 0:636056c0b5e1 332 *(unsigned char *)pDest = (char)ReadFrame_EthMAC(); // the LAN-Controller will return 0
frankvnk 0:636056c0b5e1 333 } // for the highbyte
frankvnk 0:636056c0b5e1 334 }
frankvnk 0:636056c0b5e1 335
frankvnk 0:636056c0b5e1 336
frankvnk 0:636056c0b5e1 337
frankvnk 0:636056c0b5e1 338 // does a dummy read on frame-I/O-port
frankvnk 0:636056c0b5e1 339 // NOTE: only an even number of bytes is read!
frankvnk 0:636056c0b5e1 340 void DummyReadFrame_EthMAC(unsigned short Size) // discards an EVEN number of bytes
frankvnk 0:636056c0b5e1 341 { // from RX-fifo
frankvnk 0:636056c0b5e1 342 while (Size > 1)
frankvnk 0:636056c0b5e1 343 {
frankvnk 0:636056c0b5e1 344 ReadFrame_EthMAC();
frankvnk 0:636056c0b5e1 345 Size -= 2;
frankvnk 0:636056c0b5e1 346 }
frankvnk 0:636056c0b5e1 347 }
frankvnk 0:636056c0b5e1 348
frankvnk 0:636056c0b5e1 349 // requests space in PHY on-chip memory for
frankvnk 0:636056c0b5e1 350 // storing an outgoing frame
frankvnk 0:636056c0b5e1 351 void RequestSend(unsigned short FrameSize)
frankvnk 0:636056c0b5e1 352 {
frankvnk 0:636056c0b5e1 353 unsigned int index;
frankvnk 0:636056c0b5e1 354 index = LPC_EMAC->TxProduceIndex;
frankvnk 0:636056c0b5e1 355 txptr = (unsigned short *)TX_DESC_PACKET(index);
frankvnk 0:636056c0b5e1 356 TX_DESC_CTRL(index) = FrameSize | TCTRL_LAST;
frankvnk 0:636056c0b5e1 357 }
frankvnk 0:636056c0b5e1 358
frankvnk 0:636056c0b5e1 359 // check if PHY is ready to accept the
frankvnk 0:636056c0b5e1 360 // frame we want to send
frankvnk 0:636056c0b5e1 361 unsigned int Rdy4Tx(void)
frankvnk 0:636056c0b5e1 362 {
frankvnk 0:636056c0b5e1 363 // One the LPC the ethernet controller transmits
frankvnk 0:636056c0b5e1 364 // much faster than the CPU can load its buffers
frankvnk 0:636056c0b5e1 365 // so will always be ready to accept frame
frankvnk 0:636056c0b5e1 366 return (1);
frankvnk 0:636056c0b5e1 367 }
frankvnk 0:636056c0b5e1 368
frankvnk 0:636056c0b5e1 369 // Reads length of received ethernet frame and checks
frankvnk 0:636056c0b5e1 370 // if destination address is a broadcast message or not.
frankvnk 0:636056c0b5e1 371 // Then returns the frame length
frankvnk 0:636056c0b5e1 372 unsigned short StartReadingFrame(void)
frankvnk 0:636056c0b5e1 373 {
frankvnk 0:636056c0b5e1 374 unsigned short ReceiveLength;
frankvnk 0:636056c0b5e1 375 unsigned int index;
frankvnk 0:636056c0b5e1 376
frankvnk 0:636056c0b5e1 377 index = LPC_EMAC->RxConsumeIndex;
frankvnk 0:636056c0b5e1 378 ReceiveLength = (RX_STAT_INFO(index) & RINFO_SIZE) - 3;
frankvnk 0:636056c0b5e1 379 rxptr = (unsigned short *)RX_DESC_PACKET(index);
frankvnk 0:636056c0b5e1 380 return(ReceiveLength);
frankvnk 0:636056c0b5e1 381 }
frankvnk 0:636056c0b5e1 382
frankvnk 0:636056c0b5e1 383 void StopReadingFrame(void)
frankvnk 0:636056c0b5e1 384 {
frankvnk 0:636056c0b5e1 385 unsigned int index;
frankvnk 0:636056c0b5e1 386 index = LPC_EMAC->RxConsumeIndex;
frankvnk 0:636056c0b5e1 387 if (++index == NUM_RX_FRAG) index = 0;
frankvnk 0:636056c0b5e1 388 LPC_EMAC->RxConsumeIndex = index;
frankvnk 0:636056c0b5e1 389 }
frankvnk 0:636056c0b5e1 390
frankvnk 0:636056c0b5e1 391 // check if frame has been received
frankvnk 0:636056c0b5e1 392 unsigned int CheckIfFrameReceived(void)
frankvnk 0:636056c0b5e1 393 {
frankvnk 0:636056c0b5e1 394 if (LPC_EMAC->RxProduceIndex != LPC_EMAC->RxConsumeIndex)
frankvnk 0:636056c0b5e1 395 return(1); // Yes, packet received
frankvnk 0:636056c0b5e1 396 else
frankvnk 0:636056c0b5e1 397 return(0);
frankvnk 0:636056c0b5e1 398 }