Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of WIZnetInterface by
W7500x_toe.cpp
00001 /* Copyright (C) 2012 mbed.org, MIT License 00002 * 00003 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00004 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00005 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00006 * furnished to do so, subject to the following conditions: 00007 * 00008 * The above copyright notice and this permission notice shall be included in all copies or 00009 * substantial portions of the Software. 00010 * 00011 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00012 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00013 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00014 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00015 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00016 */ 00017 #include "eth_arch.h" 00018 #if defined(TARGET_WIZwiki_W7500) || defined(TARGET_WIZwiki_W7500P) || defined(TARGET_WIZwiki_W7500ECO) 00019 00020 00021 #include "mbed.h" 00022 #include "mbed_debug.h" 00023 #include "DNSClient.h" 00024 00025 00026 /* 00027 * MDIO via GPIO 00028 * mdio via gpio is supported and related functions as follows. 00029 * - mdio_init(),mdio_read(),mdio_write() 00030 * - input_MDIO(),output_MDIO(),turnaroud_MDIO(),idle_MDIO() 00031 * called by ethernet_link() and ethernet_set_link() 00032 */ 00033 00034 #if defined (TARGET_WIZwiki_W7500) || defined(TARGET_WIZwiki_W7500ECO) 00035 00036 #define MDIO GPIO_Pin_14 00037 #define MDC GPIO_Pin_15 00038 #define GPIO_MDC GPIOB 00039 #define PHY_ADDR_IP101G 0x07 00040 #define PHY_ADDR PHY_ADDR_IP101G 00041 #define SVAL 0x2 //right shift val = 2 00042 #define PHYREG_CONTROL 0x0 //Control Register address (Contorl basic register) 00043 #define PHYREG_STATUS 0x1 //Status Register address (Status basic register) 00044 #define CNTL_DUPLEX (0x01ul<< 7) 00045 #define CNTL_AUTONEGO (0x01ul<<11) 00046 #define CNTL_SPEED (0x01ul<<12) 00047 #define MDC_WAIT (1) 00048 00049 #elif defined (TARGET_WIZwiki_W7500P) 00050 00051 #define MDIO GPIO_Pin_15 00052 #define MDC GPIO_Pin_14 00053 #define GPIO_MDC GPIOB 00054 #define PHY_ADDR_IP101G 0x01 00055 #define PHY_ADDR PHY_ADDR_IP101G 00056 #define SVAL 0x2 //right shift val = 2 00057 #define PHYREG_CONTROL 0x0 //Control Register address (Contorl basic register) 00058 #define PHYREG_STATUS 0x1 //Status Register address (Status basic register) 00059 #define CNTL_DUPLEX (0x01ul<< 7) 00060 #define CNTL_AUTONEGO (0x01ul<<11) 00061 #define CNTL_SPEED (0x01ul<<12) 00062 #define MDC_WAIT (1) 00063 00064 #endif 00065 00066 void mdio_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin_MDC, uint16_t GPIO_Pin_MDIO); 00067 void mdio_write(GPIO_TypeDef* GPIOx, uint32_t PhyRegAddr, uint32_t val); 00068 uint32_t mdio_read(GPIO_TypeDef* GPIOx, uint32_t PhyRegAddr); 00069 00070 WIZnet_Chip* WIZnet_Chip::inst; 00071 00072 WIZnet_Chip::WIZnet_Chip() 00073 { 00074 inst = this; 00075 } 00076 00077 bool WIZnet_Chip::setmac() 00078 { 00079 reg_wr_mac(SHAR, mac); 00080 return true; 00081 } 00082 00083 // Set the IP 00084 bool WIZnet_Chip::setip() 00085 { 00086 reg_wr<uint32_t>(SIPR, ip); 00087 reg_wr<uint32_t>(GAR, gateway); 00088 reg_wr<uint32_t>(SUBR, netmask); 00089 return true; 00090 } 00091 00092 bool WIZnet_Chip::setProtocol(int socket, Protocol p) 00093 { 00094 if (socket < 0) { 00095 return false; 00096 } 00097 sreg<uint8_t>(socket, Sn_MR, p); 00098 return true; 00099 } 00100 00101 bool WIZnet_Chip::connect(int socket, const char * host, int port, int timeout_ms) 00102 { 00103 if (socket < 0) { 00104 return false; 00105 } 00106 sreg<uint8_t>(socket, Sn_MR, TCP); 00107 scmd(socket, OPEN); 00108 sreg_ip(socket, Sn_DIPR, host); 00109 sreg<uint16_t>(socket, Sn_DPORT, port); 00110 sreg<uint16_t>(socket, Sn_PORT, new_port()); 00111 scmd(socket, CONNECT); 00112 Timer t; 00113 t.reset(); 00114 t.start(); 00115 while(!is_connected(socket)) { 00116 if (t.read_ms() > timeout_ms) { 00117 return false; 00118 } 00119 } 00120 return true; 00121 } 00122 00123 bool WIZnet_Chip::gethostbyname(const char* host, uint32_t* ip) 00124 { 00125 uint32_t addr = str_to_ip(host); 00126 char buf[17]; 00127 snprintf(buf, sizeof(buf), "%d.%d.%d.%d", 00128 (uint8_t)((addr>>24)&0xff), 00129 (uint8_t)((addr>>16)&0xff), 00130 (uint8_t)((addr>>8)&0xff), 00131 (uint8_t)(addr&0xff)); 00132 if (strcmp(buf, host) == 0) { 00133 *ip = addr; 00134 return true; 00135 } 00136 DNSClient client; 00137 if(client.lookup(host)) { 00138 *ip = client.ip; 00139 return true; 00140 } 00141 return false; 00142 } 00143 00144 00145 bool WIZnet_Chip::is_connected(int socket) 00146 { 00147 /* 00148 if (sreg<uint8_t>(socket, Sn_SR) == SOCK_ESTABLISHED) { 00149 return true; 00150 } 00151 */ 00152 uint8_t tmpSn_SR; 00153 tmpSn_SR = sreg<uint8_t>(socket, Sn_SR); 00154 // packet sending is possible, when state is SOCK_CLOSE_WAIT. 00155 if ((tmpSn_SR == SOCK_ESTABLISHED) || (tmpSn_SR == SOCK_CLOSE_WAIT)) { 00156 return true; 00157 } 00158 return false; 00159 } 00160 // Reset the chip & set the buffer 00161 void WIZnet_Chip::reset() 00162 { 00163 /* S/W Reset PHY */ 00164 mdio_write(GPIO_MDC, PHYREG_CONTROL, 0x8000); 00165 wait_ms(10);//for S/W reset 00166 wait_ms(10);//for MDC I/F RDY 00167 00168 mdio_init(GPIO_MDC, MDC, MDIO); 00169 00170 /* S/W Reset WZTOE */ 00171 reg_wr<uint8_t>(MR, MR_RST); 00172 // set PAD strengh and pull-up for TXD[3:0] and TXE 00173 #ifdef __DEF_USED_IC101AG__ //For using IC+101AG 00174 00175 #if defined(TARGET_WIZwiki_W7500) || defined(TARGET_WIZwiki_W7500ECO) 00176 00177 *(volatile uint32_t *)(0x41003068) = 0x64; //TXD0 00178 *(volatile uint32_t *)(0x4100306C) = 0x64; //TXD1 00179 *(volatile uint32_t *)(0x41003070) = 0x64; //TXD2 00180 *(volatile uint32_t *)(0x41003074) = 0x64; //TXD3 00181 *(volatile uint32_t *)(0x41003050) = 0x64; //TXE 00182 #endif 00183 00184 #endif 00185 00186 // set ticker counter 00187 reg_wr<uint32_t>(TIC100US, (SystemCoreClock/10000)); 00188 // write MAC address inside the WZTOE MAC address register 00189 reg_wr_mac(SHAR, mac); 00190 /* 00191 * set RX and TX buffer size 00192 * for (int socket = 0; socket < MAX_SOCK_NUM; socket++) { 00193 * sreg<uint8_t>(socket, Sn_RXBUF_SIZE, 2); 00194 * sreg<uint8_t>(socket, Sn_TXBUF_SIZE, 2); 00195 * } 00196 */ 00197 } 00198 00199 00200 bool WIZnet_Chip::close(int socket) 00201 { 00202 if (socket < 0) { 00203 return false; 00204 } 00205 // if SOCK_CLOSED, return 00206 if (sreg<uint8_t>(socket, Sn_SR) == SOCK_CLOSED) { 00207 return true; 00208 } 00209 // if SOCK_ESTABLISHED, send FIN-Packet to peer 00210 if (sreg<uint8_t>(socket, Sn_MR) == TCP) { 00211 scmd(socket, DISCON); 00212 } 00213 // close socket 00214 scmd(socket, CLOSE); 00215 // clear Socket Interrupt Register 00216 sreg<uint8_t>(socket, Sn_ICR, 0xff); 00217 return true; 00218 } 00219 00220 int WIZnet_Chip::wait_readable(int socket, int wait_time_ms, int req_size) 00221 { 00222 if (socket < 0) { 00223 return -1; 00224 } 00225 Timer t; 00226 t.reset(); 00227 t.start(); 00228 while(1) { 00229 int size = sreg<uint16_t>(socket, Sn_RX_RSR); 00230 if (size > req_size) { 00231 return size; 00232 } 00233 if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) { 00234 break; 00235 } 00236 } 00237 return -1; 00238 } 00239 00240 int WIZnet_Chip::wait_writeable(int socket, int wait_time_ms, int req_size) 00241 { 00242 if (socket < 0) { 00243 return -1; 00244 } 00245 Timer t; 00246 t.reset(); 00247 t.start(); 00248 while(1) { 00249 int size = sreg<uint16_t>(socket, Sn_TX_FSR); 00250 if (size > req_size) { 00251 return size; 00252 } 00253 if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) { 00254 break; 00255 } 00256 } 00257 return -1; 00258 } 00259 00260 int WIZnet_Chip::send(int socket, const char * str, int len) 00261 { 00262 if (socket < 0) { 00263 return -1; 00264 } 00265 00266 uint16_t ptr = sreg<uint16_t>(socket, Sn_TX_WR); 00267 uint32_t sn_tx_base = W7500x_TXMEM_BASE + (uint32_t)(socket<<18); 00268 00269 for(int i=0; i<len; i++){ 00270 *(volatile uint8_t *)(sn_tx_base + ((ptr+i)&0xFFFF)) = str[i]; 00271 //wait(0.001f); 00272 } 00273 00274 sreg<uint16_t>(socket, Sn_TX_WR, ptr + len); 00275 scmd(socket, SEND); 00276 00277 uint8_t tmp_Sn_IR; 00278 while (( (tmp_Sn_IR = sreg<uint8_t>(socket, Sn_IR)) & INT_SEND_OK) != INT_SEND_OK) { 00279 // @Jul.10, 2014 fix contant name, and udp sendto function. 00280 switch (sreg<uint8_t>(socket, Sn_SR)) { 00281 case SOCK_CLOSED : 00282 close(socket); 00283 return 0; 00284 //break; 00285 case SOCK_UDP : 00286 // ARP timeout is possible. 00287 if ((tmp_Sn_IR & INT_TIMEOUT) == INT_TIMEOUT) { 00288 sreg<uint8_t>(socket, Sn_ICR, INT_TIMEOUT); 00289 return 0; 00290 } 00291 break; 00292 default : 00293 break; 00294 } 00295 } 00296 00297 sreg<uint8_t>(socket, Sn_ICR, INT_SEND_OK); 00298 00299 return len; 00300 } 00301 00302 int WIZnet_Chip::recv(int socket, char* buf, int len) 00303 { 00304 if (socket < 0) { 00305 return -1; 00306 } 00307 uint16_t ptr = sreg<uint16_t>(socket, Sn_RX_RD); 00308 uint32_t sn_rx_base = W7500x_RXMEM_BASE + (uint32_t)(socket<<18); 00309 00310 for(int i=0; i<len; i++){ 00311 buf[i] = *(volatile uint8_t *)(sn_rx_base + ((ptr+i)&0xFFFF)); 00312 //wait(0.001f); 00313 } 00314 00315 sreg<uint16_t>(socket, Sn_RX_RD, ptr + len); 00316 scmd(socket, RECV); 00317 00318 return len; 00319 } 00320 00321 int WIZnet_Chip::new_socket() 00322 { 00323 for(int s = 0; s < MAX_SOCK_NUM; s++) { 00324 if (sreg<uint8_t>(s, Sn_SR) == SOCK_CLOSED) { 00325 return s; 00326 } 00327 } 00328 return -1; 00329 } 00330 00331 uint16_t WIZnet_Chip::new_port() 00332 { 00333 uint16_t port = rand(); 00334 port |= 49152; 00335 return port; 00336 } 00337 00338 bool WIZnet_Chip::link(int wait_time_ms) 00339 { 00340 Timer t; 00341 t.reset(); 00342 t.start(); 00343 while(1) { 00344 int is_link = ethernet_link(); 00345 00346 if (is_link) { 00347 return true; 00348 } 00349 if (wait_time_ms != (-1) && t.read_ms() > wait_time_ms) { 00350 break; 00351 } 00352 } 00353 return 0; 00354 } 00355 00356 void WIZnet_Chip::set_link(PHYMode phymode) 00357 { 00358 int speed = -1; 00359 int duplex = 0; 00360 00361 switch(phymode) { 00362 case AutoNegotiate : speed = -1; duplex = 0; break; 00363 case HalfDuplex10 : speed = 0; duplex = 0; break; 00364 case FullDuplex10 : speed = 0; duplex = 1; break; 00365 case HalfDuplex100 : speed = 1; duplex = 0; break; 00366 case FullDuplex100 : speed = 1; duplex = 1; break; 00367 } 00368 00369 ethernet_set_link(speed, duplex); 00370 } 00371 00372 uint32_t str_to_ip(const char* str) 00373 { 00374 uint32_t ip = 0; 00375 char* p = (char*)str; 00376 for(int i = 0; i < 4; i++) { 00377 ip |= atoi(p); 00378 p = strchr(p, '.'); 00379 if (p == NULL) { 00380 break; 00381 } 00382 ip <<= 8; 00383 p++; 00384 } 00385 return ip; 00386 } 00387 00388 void printfBytes(char* str, uint8_t* buf, int len) 00389 { 00390 printf("%s %d:", str, len); 00391 for(int i = 0; i < len; i++) { 00392 printf(" %02x", buf[i]); 00393 } 00394 printf("\n"); 00395 } 00396 00397 void printHex(uint8_t* buf, int len) 00398 { 00399 for(int i = 0; i < len; i++) { 00400 if ((i%16) == 0) { 00401 printf("%p", buf+i); 00402 } 00403 printf(" %02x", buf[i]); 00404 if ((i%16) == 15) { 00405 printf("\n"); 00406 } 00407 } 00408 printf("\n"); 00409 } 00410 00411 void debug_hex(uint8_t* buf, int len) 00412 { 00413 for(int i = 0; i < len; i++) { 00414 if ((i%16) == 0) { 00415 debug("%p", buf+i); 00416 } 00417 debug(" %02x", buf[i]); 00418 if ((i%16) == 15) { 00419 debug("\n"); 00420 } 00421 } 00422 debug("\n"); 00423 } 00424 00425 void WIZnet_Chip::scmd(int socket, Command cmd) 00426 { 00427 sreg<uint8_t>(socket, Sn_CR, cmd); 00428 while(sreg<uint8_t>(socket, Sn_CR)); 00429 } 00430 00431 00432 void mdio_init(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin_MDC, uint16_t GPIO_Pin_MDIO) 00433 { 00434 /* Set GPIOs for MDIO and MDC */ 00435 GPIO_InitTypeDef MDIO_InitDef; 00436 HAL_PAD_AFConfig(PAD_PB, GPIO_Pin_MDIO, PAD_AF1); 00437 HAL_PAD_AFConfig(PAD_PB, GPIO_Pin_MDC, PAD_AF1); 00438 MDIO_InitDef.GPIO_Pin = GPIO_Pin_MDC | GPIO_Pin_MDIO; 00439 MDIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; 00440 HAL_GPIO_Init(GPIOx, &MDIO_InitDef); 00441 } 00442 00443 void output_MDIO(GPIO_TypeDef* GPIOx, uint32_t val, uint32_t n) 00444 { 00445 for(val <<= (32-n); n; val<<=1, n--) 00446 { 00447 if(val & 0x80000000) 00448 HAL_GPIO_SetBits(GPIOx, MDIO); 00449 else 00450 HAL_GPIO_ResetBits(GPIOx, MDIO); 00451 00452 wait_ms(MDC_WAIT); 00453 HAL_GPIO_SetBits(GPIOx, MDC); 00454 wait_ms(MDC_WAIT); 00455 HAL_GPIO_ResetBits(GPIOx, MDC); 00456 } 00457 } 00458 00459 uint32_t input_MDIO( GPIO_TypeDef* GPIOx ) 00460 { 00461 uint32_t i, val=0; 00462 for(i=0; i<16; i++) 00463 { 00464 val <<=1; 00465 HAL_GPIO_SetBits(GPIOx, MDC); 00466 wait_ms(MDC_WAIT); 00467 HAL_GPIO_ResetBits(GPIOx, MDC); 00468 wait_ms(MDC_WAIT); 00469 val |= HAL_GPIO_ReadInputDataBit(GPIOx, MDIO); 00470 } 00471 return (val); 00472 } 00473 00474 void turnaround_MDIO( GPIO_TypeDef* GPIOx) 00475 { 00476 GPIOx->OUTENCLR = MDIO ; 00477 HAL_GPIO_SetBits(GPIOx, MDC); 00478 wait_ms(MDC_WAIT); 00479 HAL_GPIO_ResetBits(GPIOx, MDC); 00480 wait_ms(MDC_WAIT); 00481 } 00482 00483 void idle_MDIO( GPIO_TypeDef* GPIOx ) 00484 { 00485 GPIOx->OUTENSET = MDIO ; 00486 HAL_GPIO_SetBits(GPIOx,MDC); 00487 wait_ms(MDC_WAIT); 00488 HAL_GPIO_ResetBits(GPIOx, MDC); 00489 wait_ms(MDC_WAIT); 00490 } 00491 00492 uint32_t mdio_read(GPIO_TypeDef* GPIOx, uint32_t PhyRegAddr) 00493 { 00494 output_MDIO(GPIOx, 0xFFFFFFFF, 32); 00495 output_MDIO(GPIOx, 0x06, 4); 00496 output_MDIO(GPIOx, PHY_ADDR, 5); 00497 output_MDIO(GPIOx, PhyRegAddr, 5); 00498 turnaround_MDIO(GPIOx); 00499 uint32_t val = input_MDIO(GPIOx ); 00500 idle_MDIO(GPIOx); 00501 return val; 00502 } 00503 00504 void mdio_write(GPIO_TypeDef* GPIOx, uint32_t PhyRegAddr, uint32_t val) 00505 { 00506 output_MDIO(GPIOx, 0xFFFFFFFF, 32); 00507 output_MDIO(GPIOx, 0x05, 4); 00508 output_MDIO(GPIOx, PHY_ADDR, 5); 00509 output_MDIO(GPIOx, PhyRegAddr, 5); 00510 output_MDIO(GPIOx, 0x02, 2); 00511 output_MDIO(GPIOx, val, 16); 00512 idle_MDIO(GPIOx); 00513 } 00514 00515 int WIZnet_Chip::ethernet_link(void) { 00516 return ((mdio_read(GPIO_MDC, PHYREG_STATUS)>>SVAL)&0x01); 00517 } 00518 00519 void WIZnet_Chip::ethernet_set_link(int speed, int duplex) { 00520 uint32_t val=0; 00521 if((speed < 0) || (speed > 1)) { 00522 val = CNTL_AUTONEGO; 00523 } else { 00524 val = ((CNTL_SPEED&(speed<<11))|(CNTL_DUPLEX&(duplex<<7))); 00525 } 00526 mdio_write(GPIO_MDC, PHYREG_CONTROL, val); 00527 } 00528 00529 void WIZnet_Chip::reg_rd_mac(uint16_t addr, uint8_t* data) 00530 { 00531 data[0] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+3)); 00532 data[1] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+2)); 00533 data[2] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+1)); 00534 data[3] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+0)); 00535 data[4] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+7)); 00536 data[5] = *(volatile uint8_t *)(W7500x_WZTOE_BASE + (uint32_t)(addr+6)); 00537 } 00538 00539 void WIZnet_Chip::reg_wr_ip(uint16_t addr, uint8_t cb, const char* ip) 00540 { 00541 uint8_t buf[4]={0,}; 00542 uint32_t wr_ip = 0; 00543 char* p = (char*)ip; 00544 00545 for(int i = 0; i < 4; i++) { 00546 wr_ip = (wr_ip<<8); 00547 buf[i] = atoi(p); 00548 wr_ip |= buf[i]; 00549 p = strchr(p, '.'); 00550 if (p == NULL) break; 00551 p++; 00552 } 00553 *(volatile uint32_t *)(W7500x_WZTOE_BASE + (uint32_t)((cb<<16)+addr)) = wr_ip; 00554 } 00555 00556 void WIZnet_Chip::sreg_ip(int socket, uint16_t addr, const char* ip) { 00557 reg_wr_ip(addr, (uint8_t)(0x01+(socket<<2)), ip); 00558 } 00559 00560 #endif 00561 00562
Generated on Sat Jul 16 2022 21:06:07 by
1.7.2
