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:
Fri Jul 19 17:48:06 2019 +0000
Revision:
151:bde6f7da1755
Parent:
99:962440a00ead
Child:
160:6a1d1d368f80
Removed private key and certificate from semihost storage as found to be unreliable (though secure) and moved it into flash storage (reliable, simple, but visible on mbed.

Who changed what in which revision?

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