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
nic.c
00001 #include <arm_compat.h> 00002 #include <stdint.h> 00003 00004 #include "nicdefs.h" 00005 #include "semihost.h" 00006 #include "log.h" 00007 00008 #define NUM_RX_FRAMES 6 // Number of Rx Frames (== packets) was 3 00009 #define NUM_TX_FRAMES 4 // Number of Tx Frames (== packets) was 2 00010 00011 #define ETH_FRAME_LEN 1536 // Maximum Ethernet Frame Size 00012 /* 00013 Total length is NUM_RX * ((2 * 4) + (2 * 4) + 0x600) + NUM_TX * ((2 * 4) + (1 * 4) + 0x600) 00014 1 * 1552 1548 00015 00016 Can fit up to 10 in total 00017 eg 6 * 1552 + 4 * 1548 = 9312 + 6192 = 15504 00018 */ 00019 00020 00021 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile uint8_t r_buff[NUM_RX_FRAMES][ETH_FRAME_LEN]; 00022 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile uint8_t t_buff[NUM_TX_FRAMES][ETH_FRAME_LEN]; 00023 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile RX_DESC_TypeDef r_desc[NUM_RX_FRAMES]; 00024 __attribute__((section("AHBSRAM1"),aligned(8))) static volatile RX_STAT_TypeDef r_stat[NUM_RX_FRAMES]; //Must be aligned on an 8 byte boundary 00025 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile TX_DESC_TypeDef t_desc[NUM_TX_FRAMES]; 00026 __attribute__((section("AHBSRAM1"),aligned(4))) static volatile TX_STAT_TypeDef t_stat[NUM_TX_FRAMES]; 00027 00028 char* NicGetReceivedPacketOrNull(int* pSize) 00029 { 00030 if (RX_PRODUCE_INDEX == RX_CONSUME_INDEX) return NULL; 00031 00032 uint32_t info = r_stat[RX_CONSUME_INDEX].Info; 00033 *pSize = (info & RINFO_SIZE) + 1 - 4; // exclude checksum 00034 00035 return (char*)r_buff[RX_CONSUME_INDEX]; 00036 } 00037 void NicReleaseReceivedPacket() 00038 { 00039 if (RX_CONSUME_INDEX == RX_DESCRIPTOR_NUMBER) RX_CONSUME_INDEX = 0; 00040 else RX_CONSUME_INDEX++; 00041 } 00042 char* NicGetTransmitPacketOrNull(int* pSize) 00043 { 00044 if (TX_CONSUME_INDEX == 0 && TX_PRODUCE_INDEX == TX_DESCRIPTOR_NUMBER) return NULL; 00045 if (TX_PRODUCE_INDEX == TX_CONSUME_INDEX - 1) return NULL; 00046 *pSize = ETH_FRAME_LEN - 4; 00047 return (char*)t_buff[TX_PRODUCE_INDEX]; 00048 } 00049 void NicSendTransmitPacket(int size) 00050 { 00051 if (size == 0) return; 00052 t_desc[TX_PRODUCE_INDEX].Ctrl = (size - 1) | (TCTRL_INT | TCTRL_LAST); 00053 if (TX_PRODUCE_INDEX == TX_DESCRIPTOR_NUMBER) TX_PRODUCE_INDEX = 0; 00054 else TX_PRODUCE_INDEX++; 00055 } 00056 00057 static void txdscr_init() 00058 { 00059 int i; 00060 00061 for(i = 0; i < NUM_TX_FRAMES; i++) 00062 { 00063 t_desc[i].Packet = (uint32_t)&t_buff[i]; 00064 t_desc[i].Ctrl = 0; 00065 t_stat[i].Info = 0; 00066 } 00067 00068 TX_DESCRIPTOR = (uint32_t)t_desc; /* Set EMAC Transmit Descriptor Registers. */ 00069 TX_STATUS = (uint32_t)t_stat; 00070 TX_DESCRIPTOR_NUMBER = NUM_TX_FRAMES - 1; 00071 00072 TX_PRODUCE_INDEX = 0; /* Tx Descriptors Point to 0 */ 00073 } 00074 00075 static void rxdscr_init() 00076 { 00077 int i; 00078 00079 for(i = 0; i < NUM_RX_FRAMES; i++) 00080 { 00081 r_desc[i].Packet = (uint32_t)&r_buff[i]; 00082 r_desc[i].Ctrl = RCTRL_INT | (ETH_FRAME_LEN-1); 00083 r_stat[i].Info = 0; 00084 r_stat[i].HashCRC = 0; 00085 } 00086 00087 RX_DESCRIPTOR = (uint32_t)r_desc; /* Set EMAC Receive Descriptor Registers. */ 00088 RX_STATUS = (uint32_t)r_stat; //Must be aligned on an 8 byte boundary 00089 RX_DESCRIPTOR_NUMBER = NUM_RX_FRAMES - 1; 00090 00091 RX_CONSUME_INDEX = 0; /* Rx Descriptors Point to 0 */ 00092 } 00093 static int phy_write(unsigned int PhyReg, unsigned short Data) 00094 { 00095 unsigned int timeOut; 00096 00097 MADR = DP83848C_DEF_ADR | PhyReg; 00098 MWTD = Data; 00099 00100 // Wait until operation completed 00101 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) 00102 { 00103 if((MIND & MIND_BUSY) == 0) return 0; 00104 } 00105 00106 //Timed out 00107 return -1; 00108 } 00109 00110 static int phy_read(unsigned int PhyReg) 00111 { 00112 unsigned int timeOut; 00113 00114 MADR = DP83848C_DEF_ADR | PhyReg; 00115 MCMD = MCMD_READ; 00116 00117 // Wait until operation completed 00118 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) 00119 { 00120 if((MIND & MIND_BUSY) == 0) 00121 { 00122 MCMD = 0; 00123 return MRDD; // Return a 16-bit value. 00124 } 00125 } 00126 return -1; 00127 } 00128 00129 void NicLinkAddress(char *mac) 00130 { 00131 mac[5] = SA0 >> 8; 00132 mac[4] = SA0 & 0xFF; 00133 mac[3] = SA1 >> 8; 00134 mac[2] = SA1 & 0xFF; 00135 mac[1] = SA2 >> 8; 00136 mac[0] = SA2 & 0xFF; 00137 } 00138 00139 void NicLinkSetSpeedDuplex(int speed, int duplex) 00140 { 00141 unsigned short phy_data; 00142 int tout; 00143 00144 if((speed < 0) || (speed > 1)) phy_data = PHY_AUTO_NEG; 00145 else phy_data = (((unsigned short) speed << 13) | ((unsigned short) duplex << 8)); 00146 00147 phy_write(PHY_REG_BMCR, phy_data); 00148 00149 for(tout = 100; tout; tout--) __nop(); /* A short delay */ 00150 00151 phy_data = phy_read(PHY_REG_STS); 00152 00153 if(phy_data & PHY_STS_DUPLEX) 00154 { 00155 MAC2 |= MAC2_FULL_DUP; 00156 COMMAND |= CR_FULL_DUP; 00157 IPGT = IPGT_FULL_DUP; 00158 } 00159 else 00160 { 00161 MAC2 &= ~MAC2_FULL_DUP; 00162 COMMAND &= ~CR_FULL_DUP; 00163 IPGT = IPGT_HALF_DUP; 00164 } 00165 00166 if(phy_data & PHY_STS_SPEED) 00167 { 00168 SUPP &= ~SUPP_SPEED; 00169 } 00170 else 00171 { 00172 SUPP |= SUPP_SPEED; 00173 } 00174 } 00175 00176 int NicLinkIsUp(void) 00177 { 00178 return (phy_read(PHY_REG_STS) & PHY_STS_LINK); 00179 } 00180 static int phy_reset() 00181 { 00182 int regv, tout; 00183 00184 // perform PHY reset 00185 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); 00186 00187 // Wait for hardware reset to end. 00188 for(tout = 0x20000; ; tout--) 00189 { 00190 regv = phy_read(PHY_REG_BMCR); 00191 if(regv < 0 || tout == 0) return -1; // Error 00192 if(!(regv & PHY_BMCR_RESET)) break; // Reset complete. 00193 } 00194 uint32_t phy_id = (phy_read(PHY_REG_IDR1) << 16); 00195 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0); 00196 00197 //Check is the right PHY 00198 if (phy_id != DP83848C_ID) 00199 { 00200 LogTimeF("Unknown Ethernet PHY (%x)", (unsigned int)phy_id); 00201 return -1; 00202 } 00203 return 0; 00204 } 00205 int NicInit() 00206 { 00207 int tout; 00208 char mac[6]; 00209 unsigned int clock = 10; //96,000,000 00210 00211 // Reset all EMAC internal modules. 00212 MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; 00213 COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; 00214 00215 // A short delay after reset. 00216 for(tout = 100; tout; tout--) __nop(); 00217 00218 // Initialize MAC control registers. 00219 MAC1 = MAC1_PASS_ALL; 00220 MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; 00221 MAXF = ETH_FRAME_LEN; 00222 CLRT = CLRT_DEF; 00223 IPGR = IPGR_DEF; 00224 00225 // Enable Reduced MII interface. 00226 COMMAND = CR_RMII | CR_PASS_RUNT_FRM; 00227 00228 // Set clock and reset 00229 MCFG = (clock << 0x2) & MCFG_CLK_SEL; 00230 MCFG |= MCFG_RES_MII; 00231 00232 // A short delay after reset 00233 for(tout = 100; tout; tout--) __nop(); 00234 00235 // Set clock 00236 MCFG = (clock << 0x2) & MCFG_CLK_SEL; 00237 MCMD = 0; 00238 00239 // Reset Reduced MII Logic. 00240 SUPP = SUPP_RES_RMII; 00241 00242 // A short delay 00243 for (tout = 100; tout; tout--) __nop(); 00244 00245 SUPP = 0; 00246 00247 //Reset the PHY 00248 if (phy_reset()) return -1; 00249 00250 //Set the link to auto negotiate 00251 NicLinkSetSpeedDuplex(-1, 0); 00252 00253 // Set the Ethernet MAC Address registers 00254 SemihostMac(mac); 00255 SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4]; 00256 SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2]; 00257 SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0]; 00258 00259 //Initialise DMA descriptors 00260 txdscr_init(); 00261 rxdscr_init(); 00262 00263 // Set filter 00264 RX_FILTER_CTRL = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; 00265 00266 // Disable and clear EMAC interrupts 00267 INT_ENABLE = 0; 00268 INT_CLEAR = 0xFFFF; 00269 00270 //Enable receive and transmit 00271 COMMAND |= (CR_RX_EN | CR_TX_EN); 00272 MAC1 |= MAC1_REC_EN; 00273 00274 //Return success 00275 return 0; 00276 }
Generated on Tue Jul 12 2022 18:53:40 by 1.7.2