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

Committer:
andrewboyson
Date:
Thu May 20 14:32:52 2021 +0000
Revision:
200:5acbc41bf469
Parent:
160:6a1d1d368f80
Increased number of arp entries from 20 to 30 to accommodate the number of WIZ devices plus a few incoming port 80 calls from the internet.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 160:6a1d1d368f80 1 #include <arm_compat.h>
andrewboyson 60:1d8c7a1e7483 2 #include <stdint.h>
andrewboyson 61:aad055f1b0d1 3
andrewboyson 59:e0e556c8bd46 4 #include "nicdefs.h"
andrewboyson 99:962440a00ead 5 #include "semihost.h"
andrewboyson 59:e0e556c8bd46 6 #include "log.h"
andrewboyson 59:e0e556c8bd46 7
andrewboyson 61:aad055f1b0d1 8 #define NUM_RX_FRAMES 6 // Number of Rx Frames (== packets) was 3
andrewboyson 61:aad055f1b0d1 9 #define NUM_TX_FRAMES 4 // Number of Tx Frames (== packets) was 2
andrewboyson 59:e0e556c8bd46 10
andrewboyson 59:e0e556c8bd46 11 #define ETH_FRAME_LEN 1536 // Maximum Ethernet Frame Size
andrewboyson 61:aad055f1b0d1 12 /*
andrewboyson 61:aad055f1b0d1 13 Total length is NUM_RX * ((2 * 4) + (2 * 4) + 0x600) + NUM_TX * ((2 * 4) + (1 * 4) + 0x600)
andrewboyson 61:aad055f1b0d1 14 1 * 1552 1548
andrewboyson 61:aad055f1b0d1 15
andrewboyson 61:aad055f1b0d1 16 Can fit up to 10 in total
andrewboyson 61:aad055f1b0d1 17 eg 6 * 1552 + 4 * 1548 = 9312 + 6192 = 15504
andrewboyson 61:aad055f1b0d1 18 */
andrewboyson 61:aad055f1b0d1 19
andrewboyson 61:aad055f1b0d1 20
andrewboyson 61:aad055f1b0d1 21 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile uint8_t r_buff[NUM_RX_FRAMES][ETH_FRAME_LEN];
andrewboyson 61:aad055f1b0d1 22 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile uint8_t t_buff[NUM_TX_FRAMES][ETH_FRAME_LEN];
andrewboyson 61:aad055f1b0d1 23 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile RX_DESC_TypeDef r_desc[NUM_RX_FRAMES];
andrewboyson 61:aad055f1b0d1 24 __attribute__((section("AHBSRAM1"),aligned(8))) static volatile RX_STAT_TypeDef r_stat[NUM_RX_FRAMES]; //Must be aligned on an 8 byte boundary
andrewboyson 61:aad055f1b0d1 25 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile TX_DESC_TypeDef t_desc[NUM_TX_FRAMES];
andrewboyson 61:aad055f1b0d1 26 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile TX_STAT_TypeDef t_stat[NUM_TX_FRAMES];
andrewboyson 59:e0e556c8bd46 27
andrewboyson 59:e0e556c8bd46 28 char* NicGetReceivedPacketOrNull(int* pSize)
andrewboyson 59:e0e556c8bd46 29 {
andrewboyson 70:74c11fb71a15 30 if (RX_PRODUCE_INDEX == RX_CONSUME_INDEX) return NULL;
andrewboyson 59:e0e556c8bd46 31
andrewboyson 70:74c11fb71a15 32 uint32_t info = r_stat[RX_CONSUME_INDEX].Info;
andrewboyson 59:e0e556c8bd46 33 *pSize = (info & RINFO_SIZE) + 1 - 4; // exclude checksum
andrewboyson 59:e0e556c8bd46 34
andrewboyson 70:74c11fb71a15 35 return (char*)r_buff[RX_CONSUME_INDEX];
andrewboyson 59:e0e556c8bd46 36 }
andrewboyson 59:e0e556c8bd46 37 void NicReleaseReceivedPacket()
andrewboyson 59:e0e556c8bd46 38 {
andrewboyson 70:74c11fb71a15 39 if (RX_CONSUME_INDEX == RX_DESCRIPTOR_NUMBER) RX_CONSUME_INDEX = 0;
andrewboyson 70:74c11fb71a15 40 else RX_CONSUME_INDEX++;
andrewboyson 59:e0e556c8bd46 41 }
andrewboyson 59:e0e556c8bd46 42 char* NicGetTransmitPacketOrNull(int* pSize)
andrewboyson 59:e0e556c8bd46 43 {
andrewboyson 70:74c11fb71a15 44 if (TX_CONSUME_INDEX == 0 && TX_PRODUCE_INDEX == TX_DESCRIPTOR_NUMBER) return NULL;
andrewboyson 70:74c11fb71a15 45 if (TX_PRODUCE_INDEX == TX_CONSUME_INDEX - 1) return NULL;
andrewboyson 59:e0e556c8bd46 46 *pSize = ETH_FRAME_LEN - 4;
andrewboyson 70:74c11fb71a15 47 return (char*)t_buff[TX_PRODUCE_INDEX];
andrewboyson 59:e0e556c8bd46 48 }
andrewboyson 59:e0e556c8bd46 49 void NicSendTransmitPacket(int size)
andrewboyson 59:e0e556c8bd46 50 {
andrewboyson 59:e0e556c8bd46 51 if (size == 0) return;
andrewboyson 70:74c11fb71a15 52 t_desc[TX_PRODUCE_INDEX].Ctrl = (size - 1) | (TCTRL_INT | TCTRL_LAST);
andrewboyson 70:74c11fb71a15 53 if (TX_PRODUCE_INDEX == TX_DESCRIPTOR_NUMBER) TX_PRODUCE_INDEX = 0;
andrewboyson 70:74c11fb71a15 54 else TX_PRODUCE_INDEX++;
andrewboyson 59:e0e556c8bd46 55 }
andrewboyson 59:e0e556c8bd46 56
andrewboyson 59:e0e556c8bd46 57 static void txdscr_init()
andrewboyson 59:e0e556c8bd46 58 {
andrewboyson 59:e0e556c8bd46 59 int i;
andrewboyson 59:e0e556c8bd46 60
andrewboyson 59:e0e556c8bd46 61 for(i = 0; i < NUM_TX_FRAMES; i++)
andrewboyson 59:e0e556c8bd46 62 {
andrewboyson 59:e0e556c8bd46 63 t_desc[i].Packet = (uint32_t)&t_buff[i];
andrewboyson 59:e0e556c8bd46 64 t_desc[i].Ctrl = 0;
andrewboyson 59:e0e556c8bd46 65 t_stat[i].Info = 0;
andrewboyson 59:e0e556c8bd46 66 }
andrewboyson 59:e0e556c8bd46 67
andrewboyson 70:74c11fb71a15 68 TX_DESCRIPTOR = (uint32_t)t_desc; /* Set EMAC Transmit Descriptor Registers. */
andrewboyson 70:74c11fb71a15 69 TX_STATUS = (uint32_t)t_stat;
andrewboyson 70:74c11fb71a15 70 TX_DESCRIPTOR_NUMBER = NUM_TX_FRAMES - 1;
andrewboyson 59:e0e556c8bd46 71
andrewboyson 70:74c11fb71a15 72 TX_PRODUCE_INDEX = 0; /* Tx Descriptors Point to 0 */
andrewboyson 59:e0e556c8bd46 73 }
andrewboyson 59:e0e556c8bd46 74
andrewboyson 59:e0e556c8bd46 75 static void rxdscr_init()
andrewboyson 59:e0e556c8bd46 76 {
andrewboyson 59:e0e556c8bd46 77 int i;
andrewboyson 59:e0e556c8bd46 78
andrewboyson 59:e0e556c8bd46 79 for(i = 0; i < NUM_RX_FRAMES; i++)
andrewboyson 59:e0e556c8bd46 80 {
andrewboyson 59:e0e556c8bd46 81 r_desc[i].Packet = (uint32_t)&r_buff[i];
andrewboyson 59:e0e556c8bd46 82 r_desc[i].Ctrl = RCTRL_INT | (ETH_FRAME_LEN-1);
andrewboyson 59:e0e556c8bd46 83 r_stat[i].Info = 0;
andrewboyson 59:e0e556c8bd46 84 r_stat[i].HashCRC = 0;
andrewboyson 59:e0e556c8bd46 85 }
andrewboyson 59:e0e556c8bd46 86
andrewboyson 70:74c11fb71a15 87 RX_DESCRIPTOR = (uint32_t)r_desc; /* Set EMAC Receive Descriptor Registers. */
andrewboyson 70:74c11fb71a15 88 RX_STATUS = (uint32_t)r_stat; //Must be aligned on an 8 byte boundary
andrewboyson 70:74c11fb71a15 89 RX_DESCRIPTOR_NUMBER = NUM_RX_FRAMES - 1;
andrewboyson 59:e0e556c8bd46 90
andrewboyson 70:74c11fb71a15 91 RX_CONSUME_INDEX = 0; /* Rx Descriptors Point to 0 */
andrewboyson 59:e0e556c8bd46 92 }
andrewboyson 59:e0e556c8bd46 93 static int phy_write(unsigned int PhyReg, unsigned short Data)
andrewboyson 59:e0e556c8bd46 94 {
andrewboyson 59:e0e556c8bd46 95 unsigned int timeOut;
andrewboyson 59:e0e556c8bd46 96
andrewboyson 70:74c11fb71a15 97 MADR = DP83848C_DEF_ADR | PhyReg;
andrewboyson 70:74c11fb71a15 98 MWTD = Data;
andrewboyson 59:e0e556c8bd46 99
andrewboyson 59:e0e556c8bd46 100 // Wait until operation completed
andrewboyson 59:e0e556c8bd46 101 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++)
andrewboyson 59:e0e556c8bd46 102 {
andrewboyson 70:74c11fb71a15 103 if((MIND & MIND_BUSY) == 0) return 0;
andrewboyson 59:e0e556c8bd46 104 }
andrewboyson 59:e0e556c8bd46 105
andrewboyson 59:e0e556c8bd46 106 //Timed out
andrewboyson 59:e0e556c8bd46 107 return -1;
andrewboyson 59:e0e556c8bd46 108 }
andrewboyson 59:e0e556c8bd46 109
andrewboyson 59:e0e556c8bd46 110 static int phy_read(unsigned int PhyReg)
andrewboyson 59:e0e556c8bd46 111 {
andrewboyson 59:e0e556c8bd46 112 unsigned int timeOut;
andrewboyson 59:e0e556c8bd46 113
andrewboyson 70:74c11fb71a15 114 MADR = DP83848C_DEF_ADR | PhyReg;
andrewboyson 70:74c11fb71a15 115 MCMD = MCMD_READ;
andrewboyson 59:e0e556c8bd46 116
andrewboyson 59:e0e556c8bd46 117 // Wait until operation completed
andrewboyson 59:e0e556c8bd46 118 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++)
andrewboyson 59:e0e556c8bd46 119 {
andrewboyson 70:74c11fb71a15 120 if((MIND & MIND_BUSY) == 0)
andrewboyson 59:e0e556c8bd46 121 {
andrewboyson 70:74c11fb71a15 122 MCMD = 0;
andrewboyson 70:74c11fb71a15 123 return MRDD; // Return a 16-bit value.
andrewboyson 59:e0e556c8bd46 124 }
andrewboyson 59:e0e556c8bd46 125 }
andrewboyson 59:e0e556c8bd46 126 return -1;
andrewboyson 59:e0e556c8bd46 127 }
andrewboyson 59:e0e556c8bd46 128
andrewboyson 59:e0e556c8bd46 129 void NicLinkAddress(char *mac)
andrewboyson 59:e0e556c8bd46 130 {
andrewboyson 70:74c11fb71a15 131 mac[5] = SA0 >> 8;
andrewboyson 70:74c11fb71a15 132 mac[4] = SA0 & 0xFF;
andrewboyson 70:74c11fb71a15 133 mac[3] = SA1 >> 8;
andrewboyson 70:74c11fb71a15 134 mac[2] = SA1 & 0xFF;
andrewboyson 70:74c11fb71a15 135 mac[1] = SA2 >> 8;
andrewboyson 70:74c11fb71a15 136 mac[0] = SA2 & 0xFF;
andrewboyson 59:e0e556c8bd46 137 }
andrewboyson 59:e0e556c8bd46 138
andrewboyson 59:e0e556c8bd46 139 void NicLinkSetSpeedDuplex(int speed, int duplex)
andrewboyson 59:e0e556c8bd46 140 {
andrewboyson 59:e0e556c8bd46 141 unsigned short phy_data;
andrewboyson 59:e0e556c8bd46 142 int tout;
andrewboyson 59:e0e556c8bd46 143
andrewboyson 59:e0e556c8bd46 144 if((speed < 0) || (speed > 1)) phy_data = PHY_AUTO_NEG;
andrewboyson 59:e0e556c8bd46 145 else phy_data = (((unsigned short) speed << 13) | ((unsigned short) duplex << 8));
andrewboyson 59:e0e556c8bd46 146
andrewboyson 59:e0e556c8bd46 147 phy_write(PHY_REG_BMCR, phy_data);
andrewboyson 59:e0e556c8bd46 148
andrewboyson 61:aad055f1b0d1 149 for(tout = 100; tout; tout--) __nop(); /* A short delay */
andrewboyson 59:e0e556c8bd46 150
andrewboyson 59:e0e556c8bd46 151 phy_data = phy_read(PHY_REG_STS);
andrewboyson 59:e0e556c8bd46 152
andrewboyson 59:e0e556c8bd46 153 if(phy_data & PHY_STS_DUPLEX)
andrewboyson 59:e0e556c8bd46 154 {
andrewboyson 70:74c11fb71a15 155 MAC2 |= MAC2_FULL_DUP;
andrewboyson 70:74c11fb71a15 156 COMMAND |= CR_FULL_DUP;
andrewboyson 70:74c11fb71a15 157 IPGT = IPGT_FULL_DUP;
andrewboyson 59:e0e556c8bd46 158 }
andrewboyson 59:e0e556c8bd46 159 else
andrewboyson 59:e0e556c8bd46 160 {
andrewboyson 70:74c11fb71a15 161 MAC2 &= ~MAC2_FULL_DUP;
andrewboyson 70:74c11fb71a15 162 COMMAND &= ~CR_FULL_DUP;
andrewboyson 70:74c11fb71a15 163 IPGT = IPGT_HALF_DUP;
andrewboyson 59:e0e556c8bd46 164 }
andrewboyson 59:e0e556c8bd46 165
andrewboyson 59:e0e556c8bd46 166 if(phy_data & PHY_STS_SPEED)
andrewboyson 59:e0e556c8bd46 167 {
andrewboyson 70:74c11fb71a15 168 SUPP &= ~SUPP_SPEED;
andrewboyson 59:e0e556c8bd46 169 }
andrewboyson 59:e0e556c8bd46 170 else
andrewboyson 59:e0e556c8bd46 171 {
andrewboyson 70:74c11fb71a15 172 SUPP |= SUPP_SPEED;
andrewboyson 59:e0e556c8bd46 173 }
andrewboyson 59:e0e556c8bd46 174 }
andrewboyson 59:e0e556c8bd46 175
andrewboyson 59:e0e556c8bd46 176 int NicLinkIsUp(void)
andrewboyson 59:e0e556c8bd46 177 {
andrewboyson 59:e0e556c8bd46 178 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
andrewboyson 59:e0e556c8bd46 179 }
andrewboyson 59:e0e556c8bd46 180 static int phy_reset()
andrewboyson 59:e0e556c8bd46 181 {
andrewboyson 59:e0e556c8bd46 182 int regv, tout;
andrewboyson 59:e0e556c8bd46 183
andrewboyson 59:e0e556c8bd46 184 // perform PHY reset
andrewboyson 59:e0e556c8bd46 185 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET);
andrewboyson 59:e0e556c8bd46 186
andrewboyson 59:e0e556c8bd46 187 // Wait for hardware reset to end.
andrewboyson 59:e0e556c8bd46 188 for(tout = 0x20000; ; tout--)
andrewboyson 59:e0e556c8bd46 189 {
andrewboyson 59:e0e556c8bd46 190 regv = phy_read(PHY_REG_BMCR);
andrewboyson 59:e0e556c8bd46 191 if(regv < 0 || tout == 0) return -1; // Error
andrewboyson 59:e0e556c8bd46 192 if(!(regv & PHY_BMCR_RESET)) break; // Reset complete.
andrewboyson 59:e0e556c8bd46 193 }
andrewboyson 59:e0e556c8bd46 194 uint32_t phy_id = (phy_read(PHY_REG_IDR1) << 16);
andrewboyson 59:e0e556c8bd46 195 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
andrewboyson 59:e0e556c8bd46 196
andrewboyson 59:e0e556c8bd46 197 //Check is the right PHY
andrewboyson 59:e0e556c8bd46 198 if (phy_id != DP83848C_ID)
andrewboyson 59:e0e556c8bd46 199 {
andrewboyson 60:1d8c7a1e7483 200 LogTimeF("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
andrewboyson 59:e0e556c8bd46 201 return -1;
andrewboyson 59:e0e556c8bd46 202 }
andrewboyson 59:e0e556c8bd46 203 return 0;
andrewboyson 59:e0e556c8bd46 204 }
andrewboyson 59:e0e556c8bd46 205 int NicInit()
andrewboyson 59:e0e556c8bd46 206 {
andrewboyson 59:e0e556c8bd46 207 int tout;
andrewboyson 59:e0e556c8bd46 208 char mac[6];
andrewboyson 59:e0e556c8bd46 209 unsigned int clock = 10; //96,000,000
andrewboyson 59:e0e556c8bd46 210
andrewboyson 59:e0e556c8bd46 211 // Reset all EMAC internal modules.
andrewboyson 70:74c11fb71a15 212 MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
andrewboyson 70:74c11fb71a15 213 COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
andrewboyson 59:e0e556c8bd46 214
andrewboyson 59:e0e556c8bd46 215 // A short delay after reset.
andrewboyson 61:aad055f1b0d1 216 for(tout = 100; tout; tout--) __nop();
andrewboyson 59:e0e556c8bd46 217
andrewboyson 59:e0e556c8bd46 218 // Initialize MAC control registers.
andrewboyson 70:74c11fb71a15 219 MAC1 = MAC1_PASS_ALL;
andrewboyson 70:74c11fb71a15 220 MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
andrewboyson 70:74c11fb71a15 221 MAXF = ETH_FRAME_LEN;
andrewboyson 70:74c11fb71a15 222 CLRT = CLRT_DEF;
andrewboyson 70:74c11fb71a15 223 IPGR = IPGR_DEF;
andrewboyson 59:e0e556c8bd46 224
andrewboyson 59:e0e556c8bd46 225 // Enable Reduced MII interface.
andrewboyson 70:74c11fb71a15 226 COMMAND = CR_RMII | CR_PASS_RUNT_FRM;
andrewboyson 59:e0e556c8bd46 227
andrewboyson 59:e0e556c8bd46 228 // Set clock and reset
andrewboyson 70:74c11fb71a15 229 MCFG = (clock << 0x2) & MCFG_CLK_SEL;
andrewboyson 70:74c11fb71a15 230 MCFG |= MCFG_RES_MII;
andrewboyson 59:e0e556c8bd46 231
andrewboyson 59:e0e556c8bd46 232 // A short delay after reset
andrewboyson 61:aad055f1b0d1 233 for(tout = 100; tout; tout--) __nop();
andrewboyson 59:e0e556c8bd46 234
andrewboyson 59:e0e556c8bd46 235 // Set clock
andrewboyson 70:74c11fb71a15 236 MCFG = (clock << 0x2) & MCFG_CLK_SEL;
andrewboyson 70:74c11fb71a15 237 MCMD = 0;
andrewboyson 59:e0e556c8bd46 238
andrewboyson 59:e0e556c8bd46 239 // Reset Reduced MII Logic.
andrewboyson 70:74c11fb71a15 240 SUPP = SUPP_RES_RMII;
andrewboyson 59:e0e556c8bd46 241
andrewboyson 59:e0e556c8bd46 242 // A short delay
andrewboyson 61:aad055f1b0d1 243 for (tout = 100; tout; tout--) __nop();
andrewboyson 59:e0e556c8bd46 244
andrewboyson 70:74c11fb71a15 245 SUPP = 0;
andrewboyson 59:e0e556c8bd46 246
andrewboyson 59:e0e556c8bd46 247 //Reset the PHY
andrewboyson 59:e0e556c8bd46 248 if (phy_reset()) return -1;
andrewboyson 59:e0e556c8bd46 249
andrewboyson 59:e0e556c8bd46 250 //Set the link to auto negotiate
andrewboyson 59:e0e556c8bd46 251 NicLinkSetSpeedDuplex(-1, 0);
andrewboyson 59:e0e556c8bd46 252
andrewboyson 59:e0e556c8bd46 253 // Set the Ethernet MAC Address registers
andrewboyson 99:962440a00ead 254 SemihostMac(mac);
andrewboyson 70:74c11fb71a15 255 SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
andrewboyson 70:74c11fb71a15 256 SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
andrewboyson 70:74c11fb71a15 257 SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
andrewboyson 59:e0e556c8bd46 258
andrewboyson 59:e0e556c8bd46 259 //Initialise DMA descriptors
andrewboyson 59:e0e556c8bd46 260 txdscr_init();
andrewboyson 59:e0e556c8bd46 261 rxdscr_init();
andrewboyson 59:e0e556c8bd46 262
andrewboyson 59:e0e556c8bd46 263 // Set filter
andrewboyson 70:74c11fb71a15 264 RX_FILTER_CTRL = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
andrewboyson 59:e0e556c8bd46 265
andrewboyson 59:e0e556c8bd46 266 // Disable and clear EMAC interrupts
andrewboyson 70:74c11fb71a15 267 INT_ENABLE = 0;
andrewboyson 70:74c11fb71a15 268 INT_CLEAR = 0xFFFF;
andrewboyson 59:e0e556c8bd46 269
andrewboyson 59:e0e556c8bd46 270 //Enable receive and transmit
andrewboyson 70:74c11fb71a15 271 COMMAND |= (CR_RX_EN | CR_TX_EN);
andrewboyson 70:74c11fb71a15 272 MAC1 |= MAC1_REC_EN;
andrewboyson 59:e0e556c8bd46 273
andrewboyson 59:e0e556c8bd46 274 //Return success
andrewboyson 59:e0e556c8bd46 275 return 0;
andrewboyson 59:e0e556c8bd46 276 }