/****************************************************************************** * @file drv_w5500.c * @brief w5500 drivers * @version V1.0 * @author Gary * @copyright ******************************************************************************/ #include "drv_gpio.h" #include "drv_w5500.h" #include "bsp_task.h" #include "kit_time.h" #include "kit_data.h" #include "kit_debug.h" #include "ucos_ii.h" OS_EVENT *w5500_semaphore; void drv_w5500_init(W5500Item *item, uint32_t ip, uint16_t *port_array, uint32_t gateway_ip, uint32_t net_mask, uint8_t *mac, uint16_t timeout) { uint8_t buf[20]; uint32_t cnt = 0; item->server_port = port_array; //自动协商 最高位置位,否则PHY重启 buf[0] = 0x38 | 0x80 | 0x40; drv_w5500_write_comm_reg(item, W5500_PHYCFGR_REG_0x2E, buf, 1); buf[0] = 0; while(((buf[0] & 0x01) == 0x00) && (cnt++ < 50)) { bsp_task_delay_ms(100); drv_w5500_read_comm_reg(item, W5500_PHYCFGR_REG_0x2E, buf, 1); } KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 connet res %d\r\n", cnt < 100); cnt = 0; //设置网关IP WRITE_LT_INT32U(buf, cnt, gateway_ip); drv_w5500_write_comm_reg(item, W5500_GAR0_REG_0x01, buf, 4); //设置子网掩码 cnt = 0; WRITE_LT_INT32U(buf, cnt, net_mask); drv_w5500_write_comm_reg(item, W5500_SUBR0_REG_0x05, buf, 4); //设置MAC 地址 cnt = 0; kit_copy_buf(buf, mac, 6); drv_w5500_write_comm_reg(item, W5500_SHAR0_REG_0x09, buf, 6); //设置ip地址 cnt = 0; WRITE_LT_INT32U(buf, cnt, ip); drv_w5500_write_comm_reg(item, W5500_SIPR0_REG_0x0F, buf, 4); buf[0] = timeout / 200; drv_w5500_write_comm_reg(item, W5500_GAR0_REG_0x01, buf, 1); #ifdef W5500_DEBUG drv_w5500_read_comm_reg(item, W5500_GAR0_REG_0x01, buf, 4 + 4 + 6 + 4); KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 param:"); KIT_DEBUG_PRINTF_U8_BUF(buf, 4 + 4 + 6 + 4); #endif w5500_semaphore = OSSemCreate(1); } uint8_t drv_w5500_get_socket_status(W5500Item *item, uint8_t socket) { uint8_t buf[1]; uint8_t socket_reg = W5500_CREAT_SOCKET_REG(socket); //读取当前socket状态 drv_w5500_read_socket_reg(item, socket_reg, Sn_SR_0x03, buf, 1); return buf[0]; } bool drv_w5500_close_socket(W5500Item *item, uint8_t socket) { bool res = false; uint8_t tmp_buf[1]; uint32_t cnt; uint8_t socket_reg = W5500_CREAT_SOCKET_REG(socket); //读取当前socket状态 if(item->close_call != NULL) { item->close_call(socket); } drv_w5500_read_socket_reg(item, socket_reg, Sn_SR_0x03, tmp_buf, 1); KIT_MODULE_PRINTF(W5500_PRT_EN, "socket %d close st %x\r\n", socket, tmp_buf[0]); if(tmp_buf[0] != SOCK_CLOSED) { tmp_buf[0] = SOCKET_CMD_CLOSE; drv_w5500_write_socket_reg(item, socket_reg, Sn_CR_0x01, tmp_buf, 1); cnt = 0; while((tmp_buf[0] != SOCK_CLOSED) && (cnt++ < 20)) { drv_w5500_read_socket_reg(item, socket_reg, Sn_SR_0x03, tmp_buf, 1); kit_time_dly_ms(1); } if(cnt < 20) { //强制关闭一个socket tmp_buf[0] = 0; drv_w5500_write_socket_reg(item, socket_reg, Sn_MR_0x00, tmp_buf, 1); //清除socket所有中断 tmp_buf[0] = 0xFF; drv_w5500_write_socket_reg(item, socket_reg, Sn_IR_0x02, tmp_buf, 1); //关闭所有中断 tmp_buf[0] = 0; drv_w5500_write_socket_reg(item, socket_reg, Sn_IMR_0x2C, tmp_buf, 1); res = true; } } return res; } //MTU #define SOCKET_UDP_PACKSIZE 1472 //1-1472 #define SOCKET_TCP_PACKSIZE 1460 //1-1460 #define SOCKET_PPPOE_PACKSIZE 1464 //1-1464 #define SOCKET_MACRAW_PACKSIZE 1514 //1-1514 bool drv_w5500_creat_tcp_server(W5500Item *item, uint8_t socket, uint16_t local_port) { uint8_t tmp_buf[4]; uint32_t cnt; uint8_t socket_reg = W5500_CREAT_SOCKET_REG(socket); if(socket < W5500_MAX_SOCKET_NUM) { //尝试关闭socket drv_w5500_close_socket(item, socket); kit_time_dly_ms(1); //设置位TCP模式 无延时ACK tmp_buf[0] = (SOCKET_TCP & 0x07) | 0x20; drv_w5500_write_socket_reg(item, socket_reg, Sn_MR_0x00, tmp_buf, 1); //设置本地端口号 WRITE_BT_INT16U_BY_CONST_POS(tmp_buf, 0, local_port); drv_w5500_write_socket_reg(item, socket_reg, Sn_PORT_0x04, tmp_buf, 2); drv_w5500_read_socket_reg(item, socket_reg, Sn_PORT_0x04, tmp_buf, 2); KIT_MODULE_PRINTF(W5500_PRT_EN, "socket %d creat port %d\r\n", socket, READ_BT_INT16U_BY_CONST_POS(tmp_buf, 0)); //打开socket tmp_buf[0] = SOCKET_CMD_OPEN; drv_w5500_write_socket_reg(item, socket_reg, Sn_CR_0x01, tmp_buf, 1); cnt = 0; while((tmp_buf[0] != SOCK_INIT) && (cnt++ < 50)) { drv_w5500_read_socket_reg(item, socket_reg, Sn_SR_0x03, tmp_buf, 1); //KIT_MODULE_PRINTF(W5500_PRT_EN, "socket sr %x\r\n", tmp_buf[0]); kit_time_dly_ms(1); } if(cnt < 50) { //监听socket tmp_buf[0] = SOCKET_CMD_LISTEN; drv_w5500_write_socket_reg(item, socket_reg, Sn_CR_0x01, tmp_buf, 1); for(cnt = 0; cnt < 40; cnt++) { drv_w5500_read_socket_reg(item, socket_reg, Sn_SR_0x03, tmp_buf, 1); //KIT_MODULE_PRINTF(W5500_PRT_EN, "socket sr %x\r\n", tmp_buf[0]); if(tmp_buf[0] == SOCK_LISTEN) { //设置MTU WRITE_BT_INT16U_BY_CONST_POS(tmp_buf, 0, SOCKET_TCP_PACKSIZE); drv_w5500_write_socket_reg(item, socket_reg, Sn_MSSR_0x12, tmp_buf, 2); //心跳包间隔 tmp_buf[0] = 1; drv_w5500_write_socket_reg(item, socket_reg, Sn_KPALVTR_0x2F, tmp_buf, 1); KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 server %d register success\r\n", socket); //清除socket所有中断 tmp_buf[0] = 0xFF; drv_w5500_write_socket_reg(item, socket_reg, Sn_IR_0x02, tmp_buf, 1); //关闭所有中断 tmp_buf[0] = 0xFF; drv_w5500_write_socket_reg(item, socket_reg, Sn_IMR_0x2C, tmp_buf, 1); tmp_buf[0] = 1; drv_w5500_read_socket_reg(item, socket_reg, Sn_IMR_0x2C, tmp_buf, 1); KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 server %d ir %d \r\n", socket, tmp_buf[0]); return true; } kit_time_dly_ms(100); } } } KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 server %d register fail\r\n", socket); return false; } bool drv_w5500_read_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len) { bool res = false; uint8_t buf[3], err; buf[0] = reg >> 8; buf[1] = (uint8_t)reg; buf[2] = ctrl_phase << 3 | W5500_READ_ACCESS_MODE; OSSemPend(w5500_semaphore, 500, &err); if(err == OS_ERR_NONE) { drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res = (drv_spi_series_sync_send_receive(item->spi, buf, 3, value, len) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); OSSemPost(w5500_semaphore); } return res; } //len > 实际长度 + 3 bool drv_w5500_dma_read_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len) { bool res = false; uint32_t i; uint8_t err; value[0] = reg >> 8; value[1] = (uint8_t)reg; value[2] = ctrl_phase << 3 | W5500_READ_ACCESS_MODE; OSSemPend(w5500_semaphore, 500, &err); if(err == OS_ERR_NONE) { drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res = (drv_spi_dma_sync_receive(item->spi, value, len + 3) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); OSSemPost(w5500_semaphore); for(i = 0 ; i < len; i++) { value[i] = value[i + 3]; } } return res; } bool drv_w5500_write_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len) { bool res = false; uint8_t buf[3], err; buf[0] = reg >> 8; buf[1] = reg; buf[2] = ctrl_phase << 3 | W5500_WRITE_ACCESS_MODE; OSSemPend(w5500_semaphore, 500, &err); if(err == OS_ERR_NONE) { drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res = (drv_spi_series_sync_send_receive(item->spi, buf, 3, NULL, 0) == kKit_Ret_Ok); res &= (drv_spi_series_sync_send_receive(item->spi, value, len, NULL, 0) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); OSSemPost(w5500_semaphore); } return res; } bool drv_w5500_dma_write_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len) { bool res = false; uint8_t w5500_send_buf[300], err; if(len + 3 < 300) { w5500_send_buf[0] = reg >> 8; w5500_send_buf[1] = reg; w5500_send_buf[2] = ctrl_phase << 3 | W5500_WRITE_ACCESS_MODE; kit_copy_buf(&w5500_send_buf[3], value, len); OSSemPend(w5500_semaphore, 0, &err); drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res = (drv_spi_dma_sync_send(item->spi, w5500_send_buf, len + 3) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); OSSemPost(w5500_semaphore); } return res; } bool drv_w5500_read_comm_reg(W5500Item *item, uint16_t reg, uint8_t *value, uint16_t len) { bool res = false; uint8_t buf[3]; buf[0] = reg >> 8; buf[1] = reg; buf[2] = SELECT_GREG_00 | W5500_READ_ACCESS_MODE; drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res = (drv_spi_series_sync_send_receive(item->spi, buf, 3, value, len) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); return res; } bool drv_w5500_write_comm_reg(W5500Item *item, uint8_t reg, uint8_t *value, uint16_t len) { bool res = true; uint8_t buf[3]; buf[0] = reg >> 8; buf[1] = reg; buf[2] = SELECT_GREG_00 | W5500_WRITE_ACCESS_MODE; drv_gpio_set_pin_status(item->cs, kGpioStatus_Low); res &= (drv_spi_series_sync_send_receive(item->spi, buf, 3, NULL, 0) == kKit_Ret_Ok); res &= (drv_spi_series_sync_send_receive(item->spi, value, len, NULL, 0) == kKit_Ret_Ok); drv_gpio_set_pin_status(item->cs, kGpioStatus_High); return res; } void drv_w5500_poll(W5500Item *item) { static uint8_t link_off_cnt = 0; uint8_t socket_reg, buf[4]; uint16_t addr, len; uint32_t i; if((item->rcv_call != NULL) && (item->server_port != NULL)) { drv_w5500_read_comm_reg(item, W5500_PHYCFGR_REG_0x2E, buf, 1); if((buf[0] & 0x01) == 0) { buf[1] = (link_off_cnt++ > 10) ? 0x80 : 0; } else { buf[1] = link_off_cnt = 0; } for(i = 0; i < W5500_MAX_SOCKET_NUM; i++) { if(buf[1] != 0x80) { socket_reg = W5500_CREAT_SOCKET_REG(i); //读取w5500 socket状态 drv_w5500_read_socket_reg(item, socket_reg, Sn_IR_0x02, buf, 2); } else { link_off_cnt = 11; } switch(buf[1]) { //建立连接后可能存在有通信数据 case SOCK_ESTABLISHED: item->close_cnt[i] = 0; drv_w5500_read_socket_reg(item, socket_reg, Sn_RX_RSR_0x26, buf, 4); len = READ_BT_INT16U_BY_CONST_POS(buf, 0); if((len > 0) && (len < W5500_MAX_READ_BUF_SIZE)) { //获取地址并读数据 addr = READ_BT_INT16U_BY_CONST_POS(buf, 2); drv_w5500_dma_read_socket_reg(item, W5500_CREAT_SOCKET_READ_BUF(i), addr, item->read_buf, len); item->rcv_call(i, item->read_buf, len); addr += len; WRITE_BT_INT16U_BY_CONST_POS(buf, 0, addr); drv_w5500_write_socket_reg(item, socket_reg, Sn_RX_RD_0x28, buf, 2); buf[0] = SOCKET_CMD_RECV; drv_w5500_write_socket_reg(item, socket_reg, Sn_CR_0x01, buf, 1); // cnt = buf[0] = 1; // while((buf[0] != 0) && (cnt++ < 4)) // { // drv_w5500_read_socket_reg(&w5500, socket_reg, Sn_CR_0x01, buf, 1); // } } break; case SOCK_CLOSED: case SOCK_CLOSE_WAIT: if(item->close_cnt[i]++ >= 5) { if((buf[0] & 0x08) == 0x08) { buf[0] = 0x08; item->close_cnt[i] = 0; drv_w5500_write_socket_reg(item, socket_reg, Sn_IR_0x02, buf, 1); } else { drv_w5500_close_socket(item, i); drv_w5500_creat_tcp_server(item, i, item->server_port[i]); } } break; case SOCK_LISTEN: item->close_cnt[i] = 0; break; case 0x80: drv_w5500_close_socket(item, i); break; default : break; } } } } void drv_w5500_set_close_call(W5500Item *item, W5500CloseCall call) { item->close_call = call; }