add w5500 support.

This commit is contained in:
TXuian
2022-11-15 07:45:21 -08:00
parent c5872c051e
commit 629e8893e3
32 changed files with 9407 additions and 229 deletions
@@ -0,0 +1,15 @@
# Kconfig file
config BSP_USING_W5500
bool "Using w5500 "
default y
# if BSP_USING_W5500
config BSP_WIZ_RST_PIN
int
default 13
config BSP_WIZ_INT_PIN
int
default 14
# endif
@@ -0,0 +1,3 @@
SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,24 @@
## w5500 测试文档
通过board/xidatong-riscv64/third_party_driver/ethernet/connect_w5500.c 可以找到内写的3个,包含ping, tcp server test, tcp client test;
- ping 测试,测试结果包括:
- pc ping w5500
- w5500 ping baidu.com (DNS实现暂未实现,因此使用baidu.com的ip地址进行寻址)
<img src="imgs\ping w5500.png" style="zoom:60%;" />
<img src="imgs\ping baidu.png" style="zoom:60%;" />
- tcp server 测试:在xizi中调用wiz_server_op,指定port,之后可以在pc中向该端口发送数据
- wiz_server 将额外启动一个线程执行server工作,server将向client返回client发来的消息
<img src="imgs\server1.png" style="zoom:90%;" />
<img src="imgs\server0.png" style="zoom:60%;" />
- client 测试:通过wiz_client_op可以向pc中打开的tcp server发送消息
<img src="imgs\client0.png" style="zoom:67%;" />
<img src="imgs\client1.png" style="zoom:67%;" />
@@ -0,0 +1,455 @@
#include "connect_w5500.h"
#include <bus.h>
#include <dev_pin.h>
#include <drv_io_config.h>
#include <fpioa.h>
#include <string.h>
#include <xs_base.h>
#include "gpio_common.h"
#include "gpiohs.h"
#include "socket.h"
#include "w5500.h"
#define SPI_LORA_FREQUENCY 10000000
// spi operations
extern void spi_enter_cris(void);
extern void spi_exit_cris(void);
extern void spi_select_cs(void);
extern void spi_deselete_cs(void);
// global configurations for w5500 tcp connection
const uint32_t socket_tcp = 0;
const uint32_t g_wiznet_buf_size = 2048;
static wiz_NetInfo g_wiz_netinfo = {.mac = {0x00, 0x08, 0xdc, 0x11, 0x11, 0x11},
.ip = {192, 168, 31, 13},
.sn = {255, 255, 255, 0},
.gw = {192, 168, 31, 1},
.dns = {0, 0, 0, 0},
.dhcp = NETINFO_STATIC};
int network_init() {
wiz_NetInfo check_wiz_netinfo;
check_wiz_netinfo.dhcp = NETINFO_STATIC;
ctlnetwork(CN_SET_NETINFO, (void *)&g_wiz_netinfo);
ctlnetwork(CN_GET_NETINFO, (void *)&check_wiz_netinfo);
if (memcmp(&g_wiz_netinfo, &check_wiz_netinfo, sizeof(wiz_NetInfo)) != 0) {
KPrintf(
"mac: %d; ip: %d; gw: %d; sn: %d; dns: %d; dhcp: %d;\n",
memcmp(&g_wiz_netinfo.mac, &check_wiz_netinfo.mac, sizeof(uint8_t) * 6),
memcmp(&g_wiz_netinfo.ip, &check_wiz_netinfo.ip, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.sn, &check_wiz_netinfo.sn, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.gw, &check_wiz_netinfo.gw, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.dns, &check_wiz_netinfo.dns, sizeof(uint8_t) * 4),
memcmp(&g_wiz_netinfo.dhcp, &check_wiz_netinfo.dhcp, sizeof(uint8_t)));
KPrintf("WIZCHIP set network information fail.\n");
return ERROR;
}
uint8_t tmpstr[6];
ctlwizchip(CW_GET_ID, (void *)tmpstr);
KPrintf("=== %s NET CONF ===\r\n", (char *)tmpstr);
KPrintf("MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", g_wiz_netinfo.mac[0],
g_wiz_netinfo.mac[1], g_wiz_netinfo.mac[2], g_wiz_netinfo.mac[3],
g_wiz_netinfo.mac[4], g_wiz_netinfo.mac[5]);
KPrintf("SIP: %d.%d.%d.%d\r\n", g_wiz_netinfo.ip[0], g_wiz_netinfo.ip[1],
g_wiz_netinfo.ip[2], g_wiz_netinfo.ip[3]);
KPrintf("GAR: %d.%d.%d.%d\r\n", g_wiz_netinfo.gw[0], g_wiz_netinfo.gw[1],
g_wiz_netinfo.gw[2], g_wiz_netinfo.gw[3]);
KPrintf("SUB: %d.%d.%d.%d\r\n", g_wiz_netinfo.sn[0], g_wiz_netinfo.sn[1],
g_wiz_netinfo.sn[2], g_wiz_netinfo.sn[3]);
KPrintf("DNS: %d.%d.%d.%d\r\n", g_wiz_netinfo.dns[0], g_wiz_netinfo.dns[1],
g_wiz_netinfo.dns[2], g_wiz_netinfo.dns[3]);
KPrintf("======================\r\n");
return EOK;
}
/****************** spi init ******************/
static struct Bus *w5500_spi_bus;
int w5500_spi_init() {
x_err_t ret = EOK;
w5500_spi_bus = BusFind(SPI_BUS_NAME_1);
w5500_spi_bus->owner_haldev =
BusFindDevice(w5500_spi_bus, SPI_1_DEVICE_NAME_0);
w5500_spi_bus->owner_driver = BusFindDriver(w5500_spi_bus, SPI_1_DRV_NAME);
w5500_spi_bus->match(w5500_spi_bus->owner_driver,
w5500_spi_bus->owner_haldev);
struct BusConfigureInfo configure_info;
struct SpiMasterParam spi_master_param;
spi_master_param.spi_data_bit_width = 8;
spi_master_param.spi_work_mode = SPI_MODE_0 | SPI_MSB;
spi_master_param.spi_maxfrequency = SPI_LORA_FREQUENCY;
spi_master_param.spi_data_endian = 0;
configure_info.configure_cmd = OPE_CFG;
configure_info.private_data = (void *)&spi_master_param;
ret = BusDrvConfigure(w5500_spi_bus->owner_driver, &configure_info);
if (ret) {
KPrintf("spi drv OPE_CFG error drv %8p cfg %8p\n",
w5500_spi_bus->owner_driver, &spi_master_param);
return ERROR;
}
configure_info.configure_cmd = OPE_INT;
ret = BusDrvConfigure(w5500_spi_bus->owner_driver, &configure_info);
if (ret) {
KPrintf("spi drv OPE_INT error drv %8p\n", w5500_spi_bus->owner_driver);
return ERROR;
}
return EOK;
}
void spi_write_byte(uint8_t tx_data) {
struct BusBlockWriteParam write_param;
write_param.buffer = &tx_data;
write_param.size = 1;
BusDevWriteData(w5500_spi_bus->owner_haldev, &write_param);
}
uint8_t spi_read_byte(void) {
uint8_t result = 0;
struct BusBlockReadParam read_param;
read_param.buffer = &result;
read_param.size = 1;
BusDevReadData(w5500_spi_bus->owner_haldev, &read_param);
return result;
}
void spi_write_burst(uint8_t *tx_buf, uint16_t len) {
struct BusBlockWriteParam write_param;
write_param.buffer = tx_buf;
write_param.size = len;
BusDevWriteData(w5500_spi_bus->owner_haldev, &write_param);
}
void spi_read_burst(uint8_t *rx_buf, uint16_t len) {
struct BusBlockReadParam read_param;
read_param.buffer = rx_buf;
read_param.size = len;
BusDevReadData(w5500_spi_bus->owner_haldev, &read_param);
}
/****************** chip init ******************/
void wiz_reset() {
gpiohs_set_drive_mode(WIZ_RST_PIN, GPIO_DM_OUTPUT);
gpiohs_set_pin(WIZ_RST_PIN, GPIO_PV_LOW);
MdelayKTask(20);
gpiohs_set_pin(WIZ_RST_PIN, GPIO_PV_HIGH);
MdelayKTask(20);
}
void wiz_spi_handler_reg() {
// spi ops registration
#if (_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_VDM_) || \
(_WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_SPI_FDM_)
/* register SPI device CS select callback function */
gpiohs_set_drive_mode(SPI1_CS0_PIN, GPIO_DM_OUTPUT);
reg_wizchip_cs_cbfunc(spi_select_cs, spi_deselete_cs);
#else
#if (_WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_SIP_) != _WIZCHIP_IO_MODE_SIP_
#error "Unknown _WIZCHIP_IO_MODE_"
#else
reg_wizchip_cs_cbfunc(wizchip_select, wizchip_deselect);
#endif
#endif
reg_wizchip_spi_cbfunc(spi_read_byte, spi_write_byte);
reg_wizchip_cris_cbfunc(spi_enter_cris, spi_exit_cris);
reg_wizchip_spiburst_cbfunc(spi_read_burst, spi_write_burst);
}
int wiz_chip_cfg_init() {
uint8_t mem_size[2][8] = {{2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2}};
/* reset WIZnet chip internal PHY, configures PHY mode. */
if (ctlwizchip(CW_INIT_WIZCHIP, (void *)mem_size) == -1) {
KPrintf("WIZCHIP initialize failed.");
return ERROR;
}
struct wiz_NetTimeout_t net_timeout;
net_timeout.retry_cnt = 5;
net_timeout.time_100us = 20000;
ctlnetwork(CN_SET_TIMEOUT, (void *)&net_timeout);
return EOK;
}
/****************** interrupt handle ******************/
void wiz_irq_handler() {}
int wiz_interrupt_init() {
int32_t ret = -ERROR;
struct Bus *pin_bus = PinBusInitGet();
struct PinParam pin_param;
struct BusConfigureInfo pin_configure_info;
pin_configure_info.configure_cmd = OPE_CFG;
pin_configure_info.private_data = (void *)&pin_param;
pin_param.cmd = GPIO_CONFIG_MODE;
pin_param.pin = BSP_WIZ_INT_PIN;
pin_param.mode = GPIO_CFG_INPUT_PULLUP;
ret = BusDrvConfigure(pin_bus->owner_driver, &pin_configure_info);
if (ret != EOK) {
KPrintf("config pin_param %d input failed!\n", pin_param.pin);
return -ERROR;
}
pin_param.cmd = GPIO_IRQ_REGISTER;
pin_param.pin = BSP_WIZ_INT_PIN;
pin_param.irq_set.irq_mode = GPIO_IRQ_EDGE_FALLING;
pin_param.irq_set.hdr = wiz_irq_handler;
pin_param.irq_set.args = NONE;
ret = BusDrvConfigure(pin_bus->owner_driver, &pin_configure_info);
if (ret != EOK) {
KPrintf("register pin_param %d irq failed!\n", pin_param.pin);
return -ERROR;
}
pin_param.cmd = GPIO_IRQ_DISABLE;
pin_param.pin = BSP_WIZ_INT_PIN;
ret = BusDrvConfigure(pin_bus->owner_driver, &pin_configure_info);
if (ret != EOK) {
KPrintf("disable pin_param %d irq failed!\n", pin_param.pin);
return -ERROR;
}
// 4. enable interuption
pin_param.cmd = GPIO_IRQ_ENABLE;
pin_param.pin = BSP_WIZ_INT_PIN;
ret = BusDrvConfigure(pin_bus->owner_driver, &pin_configure_info);
if (ret != EOK) {
KPrintf("enable pin_param %d irq failed!\n", pin_param.pin);
return -ERROR;
}
return EOK;
return EOK;
}
int HwWiznetInit(void) {
wiz_reset();
if (EOK != w5500_spi_init()) {
return ERROR;
}
wiz_spi_handler_reg();
if (EOK != wiz_chip_cfg_init()) {
return ERROR;
}
network_init();
return EOK;
}
static void set_netinfo() {
// set g_wiz_netinfo
}
enum TCP_OPTION {
SEND_DATA = 0,
RECV_DATA,
};
uint32_t wiz_client_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint8_t dst_ip[4], uint16_t dst_port,
enum TCP_OPTION opt) {
// assert(buf_size <= g_wiznet_buf_size);
int32_t ret;
switch (getSn_SR(socket_tcp)) {
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(socket_tcp);
break;
case SOCK_CLOSED:
wiz_socket(socket_tcp, Sn_MR_TCP, 5000, 0x00);
break;
case SOCK_INIT:
KPrintf("[SOCKET CLIENT] sock init.\n");
wiz_sock_connect(socket_tcp, dst_ip, dst_port);
break;
case SOCK_ESTABLISHED:
if (getSn_IR(socket_tcp) & Sn_IR_CON) {
printf("[SOCKET CLIENT] %d:Connected\r\n", socket_tcp);
setSn_IR(socket_tcp, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(socket_tcp, buf, buf_size);
if (ret < 0) {
wiz_sock_close(socket_tcp);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
if (ret <= 0) return ret;
}
}
break;
default:
break;
}
}
void wiz_client_op_test(char *addr, uint16_t port, char *msg) {
/* argv[1]: ip
* argv[2]: port
* argv[3]: msg
*/
uint8_t client_sock = 2;
uint8_t ip[4] = {192, 168, 31, 127};
uint32_t tmp_ip[4];
KPrintf("wiz client to %s", addr);
sscanf(addr, "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2], &tmp_ip[3]);
// for (int i = 0; i < 4; ++i) {
// ip[i] = (uint8_t)tmp_ip[i];
// }
uint8_t buf[g_wiznet_buf_size];
// TODO: bug if argv[2] is not a port
// TODO: bug if msg size > 2048
KPrintf("wiz_server, send to %d.%d.%d.%d %d\n", ip[0], ip[1], ip[2], ip[3],
port);
sscanf(msg, "%s", buf);
wiz_client_op(client_sock, buf, g_wiznet_buf_size, ip, port, SEND_DATA);
MdelayKTask(10);
memset(buf, 0, g_wiznet_buf_size);
wiz_client_op(client_sock, buf, g_wiznet_buf_size, ip, port, RECV_DATA);
KPrintf("received msg: %s\n", buf);
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) |
SHELL_CMD_PARAM_NUM(3),
wiz_client_op, wiz_client_op_test,
wiz_sock_recv or wiz_sock_send data as tcp client);
int32_t wiz_server_op(uint8_t sn, uint8_t *buf, uint32_t buf_size,
uint16_t port, enum TCP_OPTION opt) {
int32_t ret = 0;
uint16_t size = 0, sentsize = 0;
switch (getSn_SR(sn)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sn) & Sn_IR_CON) {
printf("%d:Connected\r\n", sn);
setSn_IR(sn, Sn_IR_CON);
}
if (opt == SEND_DATA) {
uint32_t sent_size = 0;
ret = wiz_sock_send(socket_tcp, buf, buf_size);
if (ret < 0) {
wiz_sock_close(socket_tcp);
return ret;
}
} else if (opt == RECV_DATA) {
uint32_t size = 0;
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > buf_size) size = buf_size;
ret = wiz_sock_recv(sn, buf, size);
return ret;
}
}
break;
case SOCK_CLOSE_WAIT:
printf("%d:CloseWait\r\n", sn);
if ((ret = wiz_sock_disconnect(sn)) != SOCK_OK) return ret;
printf("%d:Closed\r\n", sn);
break;
case SOCK_INIT:
printf("%d:Listen, port [%d]\r\n", sn, port);
if ((ret = wiz_sock_listen(sn)) != SOCK_OK) return ret;
break;
case SOCK_CLOSED:
printf("%d:LBTStart\r\n", sn);
if ((ret = wiz_socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
printf("%d:Opened\r\n", sn);
break;
default:
break;
}
return 0;
}
void wiz_server(void *param) {
uint16_t port = *(uint16_t *)param;
KPrintf("wiz server, listen port: %d\n", port);
uint8_t buf[g_wiznet_buf_size];
memset(buf, 0, g_wiznet_buf_size);
int ret = 0;
while (1) {
ret = wiz_server_op(0, buf, g_wiznet_buf_size, port, RECV_DATA);
if (ret > 0) {
wiz_server_op(0, buf, g_wiznet_buf_size, port, SEND_DATA);
};
}
}
void wiz_server_test(uint16_t port) {
/* argv[1]: port
*/
int32 wiz_server_id =
KTaskCreate("wiz_server", wiz_server, (void *)&port, 4096, 25);
x_err_t flag = StartupKTask(wiz_server_id);
if (flag != EOK) {
KPrintf("StartupKTask wiz_server_id failed .\n");
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC) |
SHELL_CMD_PARAM_NUM(1),
wiz_server_op, wiz_server_test,
wiz_sock_recv or wiz_sock_send data as tcp server);
int32_t loopback_udps(uint8_t sn, uint8_t *buf, uint16_t port) {
int32_t ret;
uint16_t size, sentsize;
uint8_t destip[4];
uint16_t destport;
// uint8_t packinfo = 0;
switch (getSn_SR(sn)) {
case SOCK_UDP:
if ((size = getSn_RX_RSR(sn)) > 0) {
if (size > g_wiznet_buf_size) size = g_wiznet_buf_size;
ret = wiz_sock_recvfrom(sn, buf, size, destip, (uint16_t *)&destport);
if (ret <= 0) {
printf("%d: wiz_sock_recvfrom error. %ld\r\n", sn, ret);
return ret;
}
size = (uint16_t)ret;
sentsize = 0;
while (sentsize != size) {
ret = wiz_sock_sendto(sn, buf + sentsize, size - sentsize, destip,
destport);
if (ret < 0) {
printf("%d: wiz_sock_sendto error. %ld\r\n", sn, ret);
return ret;
}
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
}
}
break;
case SOCK_CLOSED:
printf("%d:LBUStart\r\n", sn);
if ((ret = wiz_socket(sn, Sn_MR_UDP, port, 0x00)) != sn) return ret;
printf("%d:Opened, port [%d]\r\n", sn, port);
break;
default:
break;
}
return 1;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

@@ -0,0 +1,912 @@
//*****************************************************************************
//
//! \file socket.c
//! \brief SOCKET APIs Implements file.
//! \details SOCKET APIs like as Berkeley Socket APIs.
//! \version 1.0.3
//! \date 2013/10/21
//! \par Revision history
//! <2015/02/05> Notice
//! The version history is not updated after this point.
//! Download the latest version directly from GitHub. Please visit the
//! our GitHub repository for ioLibrary.
//! >> https://github.com/Wiznet/ioLibrary_Driver
//! <2014/05/01> V1.0.3. Refer to M20140501
//! 1. Implicit type casting -> Explicit type casting.
//! 2. replace 0x01 with PACK_REMAINED in recvfrom()
//! 3. Validation a destination ip in connect() & sendto():
//! It occurs a fatal error on converting unint32 address if uint8*
//! addr parameter is not aligned by 4byte address. Copy 4 byte addr
//! value into temporary uint32 variable and then compares it.
//! <2013/12/20> V1.0.2 Refer to M20131220
//! Remove Warning.
//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104".
//! In sendto(), Add to clear timeout interrupt status
//! (Sn_IR_TIMEOUT)
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include "socket.h"
#include "wizchip_conf.h"
// M20150401 : Typing Error
//#define SOCK_ANY_PORT_NUM 0xC000;
#define SOCK_ANY_PORT_NUM 0xC000
static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
static uint16_t sock_io_mode = 0;
static uint16_t sock_is_sending = 0;
static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {
0,
0,
};
// M20150601 : For extern decleation
// static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,};
uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {
0,
};
//
#if _WIZCHIP_ == 5200
static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] = {
0,
};
#endif
// A20150601 : For integrating with W5300
#if _WIZCHIP_ == 5300
uint8_t sock_remained_byte[_WIZCHIP_SOCK_NUM_] = {
0,
}; // set by wiz_recv_data()
#endif
#define CHECK_SOCKNUM() \
do { \
if (sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \
} while (0);
#define CHECK_SOCKMODE(mode) \
do { \
if ((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \
} while (0);
#define CHECK_SOCKINIT() \
do { \
if ((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \
} while (0);
#define CHECK_SOCKDATA() \
do { \
if (len == 0) return SOCKERR_DATALEN; \
} while (0);
int8_t wiz_socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) {
CHECK_SOCKNUM();
switch (protocol) {
case Sn_MR_TCP: {
// M20150601 : Fixed the warning - taddr will never be NULL
/*
uint8_t taddr[4];
getSIPR(taddr);
*/
uint32_t taddr;
getSIPR((uint8_t *)&taddr);
if (taddr == 0) return SOCKERR_SOCKINIT;
break;
}
case Sn_MR_UDP:
case Sn_MR_MACRAW:
case Sn_MR_IPRAW:
break;
#if (_WIZCHIP_ < 5200)
case Sn_MR_PPPoE:
break;
#endif
default:
return SOCKERR_SOCKMODE;
}
// M20150601 : For SF_TCP_ALIGN & W5300
// if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG;
if ((flag & 0x04) != 0) return SOCKERR_SOCKFLAG;
#if _WIZCHIP_ == 5200
if (flag & 0x10) return SOCKERR_SOCKFLAG;
#endif
if (flag != 0) {
switch (protocol) {
case Sn_MR_TCP:
// M20150601 : For SF_TCP_ALIGN & W5300
#if _WIZCHIP_ == 5300
if ((flag & (SF_TCP_NODELAY | SF_IO_NONBLOCK | SF_TCP_ALIGN)) == 0)
return SOCKERR_SOCKFLAG;
#else
if ((flag & (SF_TCP_NODELAY | SF_IO_NONBLOCK)) == 0)
return SOCKERR_SOCKFLAG;
#endif
break;
case Sn_MR_UDP:
if (flag & SF_IGMP_VER2) {
if ((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
}
#if _WIZCHIP_ == 5500
if (flag & SF_UNI_BLOCK) {
if ((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG;
}
#endif
break;
default:
break;
}
}
wiz_sock_close(sn);
// M20150601
#if _WIZCHIP_ == 5300
setSn_MR(sn, ((uint16_t)(protocol | (flag & 0xF0))) |
(((uint16_t)(flag & 0x02)) << 7));
#else
setSn_MR(sn, (protocol | (flag & 0xF0)));
#endif
if (!port) {
port = sock_any_port++;
if (sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM;
}
setSn_PORT(sn, port);
setSn_CR(sn, Sn_CR_OPEN);
while (getSn_CR(sn))
;
// A20150401 : For release the previous sock_io_mode
sock_io_mode &= ~(1 << sn);
//
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
sock_is_sending &= ~(1 << sn);
sock_remained_size[sn] = 0;
// M20150601 : repalce 0 with PACK_COMPLETED
// sock_pack_info[sn] = 0;
sock_pack_info[sn] = PACK_COMPLETED;
//
while (getSn_SR(sn) == SOCK_CLOSED)
;
return (int8_t)sn;
}
int8_t wiz_sock_close(uint8_t sn) {
CHECK_SOCKNUM();
// A20160426 : Applied the erratum 1 of W5300
#if (_WIZCHIP_ == 5300)
// M20160503 : Wrong socket parameter. s -> sn
// if( ((getSn_MR(s)& 0x0F) == Sn_MR_TCP) && (getSn_TX_FSR(s) !=
// getSn_TxMAX(s)) )
if (((getSn_MR(sn) & 0x0F) == Sn_MR_TCP) &&
(getSn_TX_FSR(sn) != getSn_TxMAX(sn))) {
uint8_t destip[4] = {0, 0, 0, 1};
// TODO
// You can wait for completing to sending data;
// wait about 1 second;
// if you have completed to send data, skip the code of erratum 1
// ex> wait_1s();
// if (getSn_TX_FSR(s) == getSn_TxMAX(s)) continue;
//
// M20160503 : The socket() of close() calls close() itself again. It
// occures a infinite loop - close()->socket()->close()->socket()-> ~
// socket(s,Sn_MR_UDP,0x3000,0);
// sendto(s,destip,1,destip,0x3000); // send the dummy data to an unknown
// destination(0.0.0.1).
setSn_MR(sn, Sn_MR_UDP);
setSn_PORTR(sn, 0x3000);
setSn_CR(sn, Sn_CR_OPEN);
while (getSn_CR(sn) != 0)
;
while (getSn_SR(sn) != SOCK_UDP)
;
wiz_sock_sendto(
sn, destip, 1, destip,
0x3000); // send the dummy data to an unknown destination(0.0.0.1).
};
#endif
setSn_CR(sn, Sn_CR_CLOSE);
/* wait to process the command... */
while (getSn_CR(sn))
;
/* clear all interrupt of the socket. */
setSn_IR(sn, 0xFF);
// A20150401 : Release the sock_io_mode of socket n.
sock_io_mode &= ~(1 << sn);
//
sock_is_sending &= ~(1 << sn);
sock_remained_size[sn] = 0;
sock_pack_info[sn] = 0;
while (getSn_SR(sn) != SOCK_CLOSED)
;
return SOCK_OK;
}
int8_t wiz_sock_listen(uint8_t sn) {
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();
setSn_CR(sn, Sn_CR_LISTEN);
while (getSn_CR(sn))
;
while (getSn_SR(sn) != SOCK_LISTEN) {
wiz_sock_close(sn);
return SOCKERR_SOCKCLOSED;
}
return SOCK_OK;
}
int8_t wiz_sock_connect(uint8_t sn, uint8_t *addr, uint16_t port) {
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKINIT();
// M20140501 : For avoiding fatal error on memory align mismatched
// if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return
// SOCKERR_IPINVALID;
{
uint32_t taddr;
taddr = ((uint32_t)addr[0] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID;
}
//
if (port == 0) return SOCKERR_PORTZERO;
setSn_DIPR(sn, addr);
setSn_DPORT(sn, port);
setSn_CR(sn, Sn_CR_CONNECT);
while (getSn_CR(sn))
;
if (sock_io_mode & (1 << sn)) return SOCK_BUSY;
while (getSn_SR(sn) != SOCK_ESTABLISHED) {
if (getSn_IR(sn) & Sn_IR_TIMEOUT) {
setSn_IR(sn, Sn_IR_TIMEOUT);
return SOCKERR_TIMEOUT;
}
if (getSn_SR(sn) == SOCK_CLOSED) {
return SOCKERR_SOCKCLOSED;
}
}
return SOCK_OK;
}
int8_t wiz_sock_disconnect(uint8_t sn) {
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
setSn_CR(sn, Sn_CR_DISCON);
/* wait to process the command... */
while (getSn_CR(sn))
;
sock_is_sending &= ~(1 << sn);
if (sock_io_mode & (1 << sn)) return SOCK_BUSY;
while (getSn_SR(sn) != SOCK_CLOSED) {
if (getSn_IR(sn) & Sn_IR_TIMEOUT) {
wiz_sock_close(sn);
return SOCKERR_TIMEOUT;
}
}
return SOCK_OK;
}
int32_t wiz_sock_send(uint8_t sn, uint8_t *buf, uint16_t len) {
uint8_t tmp = 0;
uint16_t freesize = 0;
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKDATA();
tmp = getSn_SR(sn);
if (tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT)
return SOCKERR_SOCKSTATUS;
if (sock_is_sending & (1 << sn)) {
tmp = getSn_IR(sn);
if (tmp & Sn_IR_SENDOK) {
setSn_IR(sn, Sn_IR_SENDOK);
// M20150401 : Typing Error
//#if _WZICHIP_ == 5200
#if _WIZCHIP_ == 5200
if (getSn_TX_RD(sn) != sock_next_rd[sn]) {
setSn_CR(sn, Sn_CR_SEND);
while (getSn_CR(sn))
;
return SOCK_BUSY;
}
#endif
sock_is_sending &= ~(1 << sn);
} else if (tmp & Sn_IR_TIMEOUT) {
wiz_sock_close(sn);
return SOCKERR_TIMEOUT;
} else
return SOCK_BUSY;
}
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size.
while (1) {
freesize = getSn_TX_FSR(sn);
tmp = getSn_SR(sn);
if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) {
wiz_sock_close(sn);
return SOCKERR_SOCKSTATUS;
}
if ((sock_io_mode & (1 << sn)) && (len > freesize)) return SOCK_BUSY;
if (len <= freesize) break;
}
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ == 5200
sock_next_rd[sn] = getSn_TX_RD(sn) + len;
#endif
#if _WIZCHIP_ == 5300
setSn_TX_WRSR(sn, len);
#endif
setSn_CR(sn, Sn_CR_SEND);
/* wait to process the command... */
while (getSn_CR(sn))
;
sock_is_sending |= (1 << sn);
// M20150409 : Explicit Type Casting
// return len;
return (int32_t)len;
}
int32_t wiz_sock_recv(uint8_t sn, uint8_t *buf, uint16_t len) {
uint8_t tmp = 0;
uint16_t recvsize = 0;
// A20150601 : For integarating with W5300
#if _WIZCHIP_ == 5300
uint8_t head[2];
uint16_t mr;
#endif
//
CHECK_SOCKNUM();
CHECK_SOCKMODE(Sn_MR_TCP);
CHECK_SOCKDATA();
recvsize = getSn_RxMAX(sn);
if (recvsize < len) len = recvsize;
// A20150601 : For Integrating with W5300
#if _WIZCHIP_ == 5300
// sock_pack_info[sn] = PACK_COMPLETED; // for clear
if (sock_remained_size[sn] == 0) {
#endif
//
while (1) {
recvsize = getSn_RX_RSR(sn);
tmp = getSn_SR(sn);
if (tmp != SOCK_ESTABLISHED) {
if (tmp == SOCK_CLOSE_WAIT) {
if (recvsize != 0)
break;
else if (getSn_TX_FSR(sn) == getSn_TxMAX(sn)) {
wiz_sock_close(sn);
return SOCKERR_SOCKSTATUS;
}
} else {
wiz_sock_close(sn);
return SOCKERR_SOCKSTATUS;
}
}
if ((sock_io_mode & (1 << sn)) && (recvsize == 0)) return SOCK_BUSY;
if (recvsize != 0) break;
};
#if _WIZCHIP_ == 5300
}
#endif
// A20150601 : For integrating with W5300
#if _WIZCHIP_ == 5300
if ((sock_remained_size[sn] == 0) || (getSn_MR(sn) & Sn_MR_ALIGN)) {
mr = getMR();
if ((getSn_MR(sn) & Sn_MR_ALIGN) == 0) {
wiz_recv_data(sn, head, 2);
if (mr & MR_FS)
recvsize = (((uint16_t)head[1]) << 8) | ((uint16_t)head[0]);
else
recvsize = (((uint16_t)head[0]) << 8) | ((uint16_t)head[1]);
sock_pack_info[sn] = PACK_FIRST;
}
sock_remained_size[sn] = recvsize;
}
if (len > sock_remained_size[sn]) len = sock_remained_size[sn];
recvsize = len;
if (sock_pack_info[sn] & PACK_FIFOBYTE) {
*buf = sock_remained_byte[sn];
buf++;
sock_pack_info[sn] &= ~(PACK_FIFOBYTE);
recvsize -= 1;
sock_remained_size[sn] -= 1;
}
if (recvsize != 0) {
wiz_recv_data(sn, buf, recvsize);
setSn_CR(sn, Sn_CR_RECV);
while (getSn_CR(sn))
;
}
sock_remained_size[sn] -= recvsize;
if (sock_remained_size[sn] != 0) {
sock_pack_info[sn] |= PACK_REMAINED;
if (recvsize & 0x1) sock_pack_info[sn] |= PACK_FIFOBYTE;
} else
sock_pack_info[sn] = PACK_COMPLETED;
if (getSn_MR(sn) & Sn_MR_ALIGN) sock_remained_size[sn] = 0;
// len = recvsize;
#else
if (recvsize < len) len = recvsize;
wiz_recv_data(sn, buf, len);
setSn_CR(sn, Sn_CR_RECV);
while (getSn_CR(sn))
;
#endif
// M20150409 : Explicit Type Casting
// return len;
return (int32_t)len;
}
int32_t wiz_sock_sendto(uint8_t sn, uint8_t *buf, uint16_t len, uint8_t *addr,
uint16_t port) {
uint8_t tmp = 0;
uint16_t freesize = 0;
uint32_t taddr;
CHECK_SOCKNUM();
switch (getSn_MR(sn) & 0x0F) {
case Sn_MR_UDP:
case Sn_MR_MACRAW:
// break;
// #if ( _WIZCHIP_ < 5200 )
case Sn_MR_IPRAW:
break;
// #endif
default:
return SOCKERR_SOCKMODE;
}
CHECK_SOCKDATA();
// M20140501 : For avoiding fatal error on memory align mismatched
// if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
//{
// uint32_t taddr;
taddr = ((uint32_t)addr[0]) & 0x000000FF;
taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF);
taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF);
//}
//
// if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID;
if ((taddr == 0) && ((getSn_MR(sn) & Sn_MR_MACRAW) != Sn_MR_MACRAW))
return SOCKERR_IPINVALID;
if ((port == 0) && ((getSn_MR(sn) & Sn_MR_MACRAW) != Sn_MR_MACRAW))
return SOCKERR_PORTZERO;
tmp = getSn_SR(sn);
//#if ( _WIZCHIP_ < 5200 )
if ((tmp != SOCK_MACRAW) && (tmp != SOCK_UDP) && (tmp != SOCK_IPRAW))
return SOCKERR_SOCKSTATUS;
//#else
// if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS;
//#endif
setSn_DIPR(sn, addr);
setSn_DPORT(sn, port);
freesize = getSn_TxMAX(sn);
if (len > freesize) len = freesize; // check size not to exceed MAX size.
while (1) {
freesize = getSn_TX_FSR(sn);
if (getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if ((sock_io_mode & (1 << sn)) && (len > freesize)) return SOCK_BUSY;
if (len <= freesize) break;
};
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ < 5500 // M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
getSIPR((uint8_t *)&taddr);
if (taddr == 0) {
getSUBR((uint8_t *)&taddr);
setSUBR((uint8_t *)"\x00\x00\x00\x00");
} else
taddr = 0;
#endif
// A20150601 : For W5300
#if _WIZCHIP_ == 5300
setSn_TX_WRSR(sn, len);
#endif
//
setSn_CR(sn, Sn_CR_SEND);
/* wait to process the command... */
while (getSn_CR(sn))
;
while (1) {
tmp = getSn_IR(sn);
if (tmp & Sn_IR_SENDOK) {
setSn_IR(sn, Sn_IR_SENDOK);
break;
}
// M:20131104
// else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT;
else if (tmp & Sn_IR_TIMEOUT) {
setSn_IR(sn, Sn_IR_TIMEOUT);
// M20150409 : Fixed the lost of sign bits by type casting.
// len = (uint16_t)SOCKERR_TIMEOUT;
// break;
#if _WIZCHIP_ < 5500 // M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
if (taddr) setSUBR((uint8_t *)&taddr);
#endif
return SOCKERR_TIMEOUT;
}
////////////
}
#if _WIZCHIP_ < 5500 // M20150401 : for WIZCHIP Errata #4, #5 (ARP errata)
if (taddr) setSUBR((uint8_t *)&taddr);
#endif
// M20150409 : Explicit Type Casting
// return len;
return (int32_t)len;
}
int32_t wiz_sock_recvfrom(uint8_t sn, uint8_t *buf, uint16_t len, uint8_t *addr,
uint16_t *port) {
// M20150601 : For W5300
#if _WIZCHIP_ == 5300
uint16_t mr;
uint16_t mr1;
#else
uint8_t mr;
#endif
//
uint8_t head[8];
uint16_t pack_len = 0;
CHECK_SOCKNUM();
// CHECK_SOCKMODE(Sn_MR_UDP);
// A20150601
#if _WIZCHIP_ == 5300
mr1 = getMR();
#endif
switch ((mr = getSn_MR(sn)) & 0x0F) {
case Sn_MR_UDP:
case Sn_MR_IPRAW:
case Sn_MR_MACRAW:
break;
#if (_WIZCHIP_ < 5200)
case Sn_MR_PPPoE:
break;
#endif
default:
return SOCKERR_SOCKMODE;
}
CHECK_SOCKDATA();
if (sock_remained_size[sn] == 0) {
while (1) {
pack_len = getSn_RX_RSR(sn);
if (getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if ((sock_io_mode & (1 << sn)) && (pack_len == 0)) return SOCK_BUSY;
if (pack_len != 0) break;
};
}
// D20150601 : Move it to bottom
// sock_pack_info[sn] = PACK_COMPLETED;
switch (mr & 0x07) {
case Sn_MR_UDP:
if (sock_remained_size[sn] == 0) {
wiz_recv_data(sn, head, 8);
setSn_CR(sn, Sn_CR_RECV);
while (getSn_CR(sn))
;
// read peer's IP address, port number & packet length
// A20150601 : For W5300
#if _WIZCHIP_ == 5300
if (mr1 & MR_FS) {
addr[0] = head[1];
addr[1] = head[0];
addr[2] = head[3];
addr[3] = head[2];
*port = head[5];
*port = (*port << 8) + head[4];
sock_remained_size[sn] = head[7];
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[6];
} else {
#endif
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
sock_remained_size[sn] = head[6];
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7];
#if _WIZCHIP_ == 5300
}
#endif
sock_pack_info[sn] = PACK_FIRST;
}
if (len < sock_remained_size[sn])
pack_len = len;
else
pack_len = sock_remained_size[sn];
// A20150601 : For W5300
len = pack_len;
#if _WIZCHIP_ == 5300
if (sock_pack_info[sn] & PACK_FIFOBYTE) {
*buf++ = sock_remained_byte[sn];
pack_len -= 1;
sock_remained_size[sn] -= 1;
sock_pack_info[sn] &= ~PACK_FIFOBYTE;
}
#endif
//
// Need to packet length check (default 1472)
//
wiz_recv_data(sn, buf, pack_len); // data copy.
break;
case Sn_MR_MACRAW:
if (sock_remained_size[sn] == 0) {
wiz_recv_data(sn, head, 2);
setSn_CR(sn, Sn_CR_RECV);
while (getSn_CR(sn))
;
// read peer's IP address, port number & packet length
sock_remained_size[sn] = head[0];
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[1] - 2;
#if _WIZCHIP_ == W5300
if (sock_remained_size[sn] & 0x01)
sock_remained_size[sn] = sock_remained_size[sn] + 1 - 4;
else
sock_remained_size[sn] -= 4;
#endif
if (sock_remained_size[sn] > 1514) {
wiz_sock_close(sn);
return SOCKFATAL_PACKLEN;
}
sock_pack_info[sn] = PACK_FIRST;
}
if (len < sock_remained_size[sn])
pack_len = len;
else
pack_len = sock_remained_size[sn];
wiz_recv_data(sn, buf, pack_len);
break;
//#if ( _WIZCHIP_ < 5200 )
case Sn_MR_IPRAW:
if (sock_remained_size[sn] == 0) {
wiz_recv_data(sn, head, 6);
setSn_CR(sn, Sn_CR_RECV);
while (getSn_CR(sn))
;
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
sock_remained_size[sn] = head[4];
// M20150401 : For Typing Error
// sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5];
sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[5];
sock_pack_info[sn] = PACK_FIRST;
}
//
// Need to packet length check
//
if (len < sock_remained_size[sn])
pack_len = len;
else
pack_len = sock_remained_size[sn];
wiz_recv_data(sn, buf, pack_len); // data copy.
break;
//#endif
default:
wiz_recv_ignore(sn, pack_len); // data copy.
sock_remained_size[sn] = pack_len;
break;
}
setSn_CR(sn, Sn_CR_RECV);
/* wait to process the command... */
while (getSn_CR(sn))
;
sock_remained_size[sn] -= pack_len;
// M20150601 :
// if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01;
if (sock_remained_size[sn] != 0) {
sock_pack_info[sn] |= PACK_REMAINED;
#if _WIZCHIP_ == 5300
if (pack_len & 0x01) sock_pack_info[sn] |= PACK_FIFOBYTE;
#endif
} else
sock_pack_info[sn] = PACK_COMPLETED;
#if _WIZCHIP_ == 5300
pack_len = len;
#endif
//
// M20150409 : Explicit Type Casting
// return pack_len;
return (int32_t)pack_len;
}
int8_t wiz_ctlsocket(uint8_t sn, ctlsock_type cstype, void *arg) {
uint8_t tmp = 0;
CHECK_SOCKNUM();
switch (cstype) {
case CS_SET_IOMODE:
tmp = *((uint8_t *)arg);
if (tmp == SOCK_IO_NONBLOCK)
sock_io_mode |= (1 << sn);
else if (tmp == SOCK_IO_BLOCK)
sock_io_mode &= ~(1 << sn);
else
return SOCKERR_ARG;
break;
case CS_GET_IOMODE:
// M20140501 : implict type casting -> explict type casting
//*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001;
*((uint8_t *)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001);
//
break;
case CS_GET_MAXTXBUF:
*((uint16_t *)arg) = getSn_TxMAX(sn);
break;
case CS_GET_MAXRXBUF:
*((uint16_t *)arg) = getSn_RxMAX(sn);
break;
case CS_CLR_INTERRUPT:
if ((*(uint8_t *)arg) > SIK_ALL) return SOCKERR_ARG;
setSn_IR(sn, *(uint8_t *)arg);
break;
case CS_GET_INTERRUPT:
*((uint8_t *)arg) = getSn_IR(sn);
break;
#if _WIZCHIP_ != 5100
case CS_SET_INTMASK:
if ((*(uint8_t *)arg) > SIK_ALL) return SOCKERR_ARG;
setSn_IMR(sn, *(uint8_t *)arg);
break;
case CS_GET_INTMASK:
*((uint8_t *)arg) = getSn_IMR(sn);
break;
#endif
default:
return SOCKERR_ARG;
}
return SOCK_OK;
}
int8_t wiz_setsockopt(uint8_t sn, sockopt_type sotype, void *arg) {
// M20131220 : Remove warning
// uint8_t tmp;
CHECK_SOCKNUM();
switch (sotype) {
case SO_TTL:
setSn_TTL(sn, *(uint8_t *)arg);
break;
case SO_TOS:
setSn_TOS(sn, *(uint8_t *)arg);
break;
case SO_MSS:
setSn_MSSR(sn, *(uint16_t *)arg);
break;
case SO_DESTIP:
setSn_DIPR(sn, (uint8_t *)arg);
break;
case SO_DESTPORT:
setSn_DPORT(sn, *(uint16_t *)arg);
break;
#if _WIZCHIP_ != 5100
case SO_KEEPALIVESEND:
CHECK_SOCKMODE(Sn_MR_TCP);
#if _WIZCHIP_ > 5200
if (getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT;
#endif
setSn_CR(sn, Sn_CR_SEND_KEEP);
while (getSn_CR(sn) != 0) {
// M20131220
// if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT)
if (getSn_IR(sn) & Sn_IR_TIMEOUT) {
setSn_IR(sn, Sn_IR_TIMEOUT);
return SOCKERR_TIMEOUT;
}
}
break;
#if !((_WIZCHIP_ == 5100) || (_WIZCHIP_ == 5200))
case SO_KEEPALIVEAUTO:
CHECK_SOCKMODE(Sn_MR_TCP);
setSn_KPALVTR(sn, *(uint8_t *)arg);
break;
#endif
#endif
default:
return SOCKERR_ARG;
}
return SOCK_OK;
}
int8_t wiz_getsockopt(uint8_t sn, sockopt_type sotype, void *arg) {
CHECK_SOCKNUM();
switch (sotype) {
case SO_FLAG:
*(uint8_t *)arg = getSn_MR(sn) & 0xF0;
break;
case SO_TTL:
*(uint8_t *)arg = getSn_TTL(sn);
break;
case SO_TOS:
*(uint8_t *)arg = getSn_TOS(sn);
break;
case SO_MSS:
*(uint16_t *)arg = getSn_MSSR(sn);
break;
case SO_DESTIP:
getSn_DIPR(sn, (uint8_t *)arg);
break;
case SO_DESTPORT:
*(uint16_t *)arg = getSn_DPORT(sn);
break;
#if _WIZCHIP_ > 5200
case SO_KEEPALIVEAUTO:
CHECK_SOCKMODE(Sn_MR_TCP);
*(uint16_t *)arg = getSn_KPALVTR(sn);
break;
#endif
case SO_SENDBUF:
*(uint16_t *)arg = getSn_TX_FSR(sn);
break;
case SO_RECVBUF:
*(uint16_t *)arg = getSn_RX_RSR(sn);
break;
case SO_STATUS:
*(uint8_t *)arg = getSn_SR(sn);
break;
case SO_REMAINSIZE:
if (getSn_MR(sn) & Sn_MR_TCP)
*(uint16_t *)arg = getSn_RX_RSR(sn);
else
*(uint16_t *)arg = sock_remained_size[sn];
break;
case SO_PACKINFO:
// CHECK_SOCKMODE(Sn_MR_TCP);
#if _WIZCHIP_ != 5300
if ((getSn_MR(sn) == Sn_MR_TCP)) return SOCKERR_SOCKMODE;
#endif
*(uint8_t *)arg = sock_pack_info[sn];
break;
default:
return SOCKERR_SOCKOPT;
}
return SOCK_OK;
}
@@ -0,0 +1,35 @@
#include <assert.h>
#include <connect_w5500.h>
#include <drv_io_config.h>
#include <fpioa.h>
#include <sleep.h>
#include <xs_base.h>
#include "gpio_common.h"
#include "gpiohs.h"
// #define SPI1_CS_GPIONUM 24
static x_base g_w5500_spi_lock;
/**
* @brief 进入临界区
* @retval None
*/
void spi_enter_cris(void) { g_w5500_spi_lock = DisableLocalInterrupt(); }
/**
* @brief 退出临界区
* @retval None
*/
void spi_exit_cris(void) { EnableLocalInterrupt(g_w5500_spi_lock); }
/**
* @brief 片选信号输出低电平
* @retval None
*/
void spi_select_cs(void) { gpiohs_set_pin(SPI1_CS0_PIN, GPIO_PV_LOW); }
/**
* @brief 片选信号输出高电平
* @retval None
*/
void spi_deselete_cs(void) { gpiohs_set_pin(SPI1_CS0_PIN, GPIO_PV_HIGH); }
@@ -0,0 +1,255 @@
//*****************************************************************************
//
//! \file w5500.c
//! \brief W5500 HAL Interface.
//! \version 1.0.2
//! \date 2013/10/21
//! \par Revision history
//! <2015/02/05> Notice
//! The version history is not updated after this point.
//! Download the latest version directly from GitHub. Please visit the
//! our GitHub repository for ioLibrary.
//! >> https://github.com/Wiznet/ioLibrary_Driver
//! <2014/05/01> V1.0.2
//! 1. Implicit type casting -> Explicit type casting. Refer to
//! M20140501
//! Fixed the problem on porting into under 32bit MCU
//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh
//! Thank for your interesting and serious advices.
//! <2013/12/20> V1.0.1
//! 1. Remove warning
//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case
//! _WIZCHIP_IO_MODE_SPI_FDM_
//! for loop optimized(removed). refer to M20131220
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
//#include <stdio.h>
#include "w5500.h"
#define _W5500_SPI_VDM_OP_ 0x00
#define _W5500_SPI_FDM_OP_LEN1_ 0x01
#define _W5500_SPI_FDM_OP_LEN2_ 0x02
#define _W5500_SPI_FDM_OP_LEN4_ 0x03
#if (_WIZCHIP_ == 5500)
////////////////////////////////////////////////////
uint8_t WIZCHIP_READ(uint32_t AddrSel) {
uint8_t ret;
uint8_t spi_data[3];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
if (!WIZCHIP.IF.SPI._read_burst ||
!WIZCHIP.IF.SPI._write_burst) // byte operation
{
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
} else // burst operation
{
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
}
ret = WIZCHIP.IF.SPI._read_byte();
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
return ret;
}
void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) {
uint8_t spi_data[4];
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
// if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) // byte
// operation
if (!WIZCHIP.IF.SPI._write_burst) // byte operation
{
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
WIZCHIP.IF.SPI._write_byte(wb);
} else // burst operation
{
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
spi_data[3] = wb;
WIZCHIP.IF.SPI._write_burst(spi_data, 4);
}
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t *pBuf, uint16_t len) {
uint8_t spi_data[3];
uint16_t i;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);
if (!WIZCHIP.IF.SPI._read_burst ||
!WIZCHIP.IF.SPI._write_burst) // byte operation
{
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
for (i = 0; i < len; i++)
pBuf[i] = WIZCHIP.IF.SPI._read_byte();
} else // burst operation
{
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._read_burst(pBuf, len);
}
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t *pBuf, uint16_t len) {
uint8_t spi_data[3];
uint16_t i;
WIZCHIP_CRITICAL_ENTER();
WIZCHIP.CS._select();
AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_);
if (!WIZCHIP.IF.SPI._write_burst) // byte operation
{
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8);
WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0);
for (i = 0; i < len; i++)
WIZCHIP.IF.SPI._write_byte(pBuf[i]);
} else // burst operation
{
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = (AddrSel & 0x000000FF) >> 0;
WIZCHIP.IF.SPI._write_burst(spi_data, 3);
WIZCHIP.IF.SPI._write_burst(pBuf, len);
}
WIZCHIP.CS._deselect();
WIZCHIP_CRITICAL_EXIT();
}
uint16_t getSn_TX_FSR(uint8_t sn) {
uint16_t val = 0, val1 = 0;
do {
val1 = WIZCHIP_READ(Sn_TX_FSR(sn));
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn), 1));
if (val1 != 0) {
val = WIZCHIP_READ(Sn_TX_FSR(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn), 1));
}
} while (val != val1);
return val;
}
uint16_t getSn_RX_RSR(uint8_t sn) {
uint16_t val = 0, val1 = 0;
do {
val1 = WIZCHIP_READ(Sn_RX_RSR(sn));
val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn), 1));
if (val1 != 0) {
val = WIZCHIP_READ(Sn_RX_RSR(sn));
val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn), 1));
}
} while (val != val1);
return val;
}
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
uint16_t ptr = 0;
uint32_t addrsel = 0;
if (len == 0)
return;
ptr = getSn_TX_WR(sn);
// M20140501 : implict type casting -> explict type casting
// addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
//
WIZCHIP_WRITE_BUF(addrsel, wizdata, len);
ptr += len;
setSn_TX_WR(sn, ptr);
}
void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) {
uint16_t ptr = 0;
uint32_t addrsel = 0;
if (len == 0)
return;
ptr = getSn_RX_RD(sn);
// M20140501 : implict type casting -> explict type casting
// addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3);
//
WIZCHIP_READ_BUF(addrsel, wizdata, len);
ptr += len;
setSn_RX_RD(sn, ptr);
}
void wiz_recv_ignore(uint8_t sn, uint16_t len) {
uint16_t ptr = 0;
ptr = getSn_RX_RD(sn);
ptr += len;
setSn_RX_RD(sn, ptr);
}
#endif
@@ -0,0 +1,251 @@
#include "wiz_ping.h"
#include <shell.h>
#include <stdio.h>
#include <string.h>
#include <xs_base.h>
#include <xs_ktask.h>
#define Sn_PROTO(ch) (0x001408 + (ch << 5))
#define PING_BIND_PORT 3000
PINGMSGR PingRequest = {0};
PINGMSGR PingReply = {0};
static uint16_t ping_RandomID = 0x1234;
static uint16_t ping_RandomSeqNum = 0x4321;
uint8_t ping_reply_received = 0;
uint8_t ping_req = 0;
uint8_t ping_rep = 0;
uint8_t ping_cnt = 0;
uint8_t ping_rep_buf[150] = {0};
// ping状态机
#define PING_STA_FREE 0
#define PING_STA_OPEN 1
#define PING_STA_SEND 2
#define PING_STA_WAIT 3
#define PING_STA_CLOSE 4
uint8_t ping_sta = PING_STA_FREE;
//当前ping的设备的序号
uint8_t ping_socket = 0;
#define bswap_16(A) ((((uint16)(A)&0xff00) >> 8) | (((uint16)(A)&0x00ff) << 8))
uint16_t htons(uint16_t n) {
union {
int i;
char c;
} u = {1};
return u.c ? bswap_16(n) : n;
}
uint16_t checksum(uint8_t *src, uint32_t len) {
uint16_t sum, tsum, i, j;
uint32_t lsum;
j = len >> 1;
lsum = 0;
for (i = 0; i < j; i++) {
tsum = src[i * 2];
tsum = tsum << 8;
tsum += src[i * 2 + 1];
lsum += tsum;
}
if (len % 2) {
tsum = src[i * 2];
lsum += (tsum << 8);
}
sum = lsum;
sum = ~(sum + (lsum >> 16));
return (uint16_t)sum;
}
/**
*@brief 设定次数ping外网IP函数
*@param sn- socket number
*@param addr- 外网IP地址
*@param pCount- ping的次数
*@return ping成功次数
*/
uint8_t ping_count(uint8_t sn, uint16_t pCount, uint8_t *addr) {
uint16_t rlen, cnt, i;
ping_reply_received = 0;
ping_req = 0;
ping_rep = 0;
KPrintf("Ping:%d.%d.%d.%d\r\n", (addr[0]), (addr[1]), (addr[2]), (addr[3]));
for (i = 0; i < pCount + 1; i++) /*循环ping pCount次*/
{
switch (getSn_SR(sn)) /*获取socket状态*/
{
case SOCK_CLOSED: /*socket关闭状态*/
{
wiz_sock_close(sn);
/* Create Socket */
IINCHIP_WRITE(Sn_PROTO(sn), IPPROTO_ICMP); /*设置ICMP 协议*/
if (wiz_socket(sn, Sn_MR_IPRAW, PING_BIND_PORT, 0) !=
0) /*判断ip raw模式socket是否开启*/
{
}
/* Check socket register */
while (getSn_SR(sn) != SOCK_IPRAW) {
MdelayKTask(50);
};
break;
}
case SOCK_IPRAW: /*ip raw模式*/
{
cnt = 0;
ping_request(sn, addr); /*发送Ping请求*/
ping_req++;
while (1) {
if ((rlen = getSn_RX_RSR(sn)) > 0) {
rlen = ping_reply(sn, addr, rlen); /*获取回复信息*/
ping_rep++;
if (ping_reply_received) {
break;
}
}
if ((cnt > 300)) {
cnt = 0;
break;
} else {
cnt++;
MdelayKTask(10);
}
}
break;
}
default:
break;
}
if (ping_req >= pCount) {
wiz_sock_close(sn);
}
}
return ping_rep;
}
/**
*@brief ping请求函数
*@param sn- socket number
*@param addr- P地址
*@return 无
*/
uint8_t ping_request(uint8_t sn, uint8_t *addr) {
uint8_t *buffer;
uint16_t i, temp_len = 0;
ping_reply_received = 0; /*ping 回复初始化标志位*/
PingRequest.Type = PING_REQUEST; /*Ping-Request*/
PingRequest.Code = CODE_ZERO; /*总是 '0'*/
PingRequest.ID = htons(ping_RandomID++); /*设置ping响应ID为随机的整型变量*/
PingRequest.SeqNum =
htons(ping_RandomSeqNum++); /*设置ping响应的序列号为随机整形变量*/
for (i = 0; i < PING_BUF_LEN; i++) {
PingRequest.Data[i] = (i) % 8; /*ping相应的数在'0'~'8*/
}
PingRequest.CheckSum = 0;
/* 计算响应次数*/
PingRequest.CheckSum =
htons(checksum((uint8_t *)&PingRequest, sizeof(PingRequest)));
/*发送ping响应到目的方 */
if (wiz_sock_sendto(sn, (uint8_t *)&PingRequest, sizeof(PingRequest), addr,
PING_BIND_PORT) == 0) {
KPrintf("Fail to send ping-reply packet\r\n");
} else {
KPrintf("ping send\n");
}
return 0;
}
/**
*@brief 解析Ping回复
*@param sn- socket number
*@param addr- Ping地址
*@return 无
*/
uint8_t ping_reply(uint8_t sn, uint8_t *addr, uint16_t rlen) {
uint16_t tmp_checksum;
uint16_t len;
uint16_t i;
uint16_t port = PING_BIND_PORT;
PINGMSGR PingReply;
memset(ping_rep_buf, 0, sizeof(ping_rep_buf));
len = wiz_sock_recvfrom(sn, ping_rep_buf, rlen, addr,
&port); /*从目的端接收数据*/
if (ping_rep_buf[0] == PING_REPLY) {
PingReply.Type = ping_rep_buf[0];
PingReply.Code = ping_rep_buf[1];
PingReply.CheckSum = (ping_rep_buf[3] << 8) + ping_rep_buf[2];
PingReply.ID = (ping_rep_buf[5] << 8) + ping_rep_buf[4];
PingReply.SeqNum = (ping_rep_buf[7] << 8) + ping_rep_buf[6];
for (i = 0; i < len - 8; i++) {
PingReply.Data[i] = ping_rep_buf[8 + i];
}
tmp_checksum = ~checksum(ping_rep_buf, len); /*检查ping回复的次数*/
if (tmp_checksum != 0xffff) {
KPrintf("tmp_checksum = %x\r\n", tmp_checksum);
} else {
KPrintf("Reply from %3d.%3d.%3d.%3d ID=%x Byte=%d\r\n\r\n", (addr[0]),
(addr[1]), (addr[2]), (addr[3]), htons(PingReply.ID), (rlen + 6));
ping_reply_received = 1; /*当退出ping回复循环时,设置ping回复标志为1*/
}
} else if (ping_rep_buf[0] == PING_REQUEST) {
PingReply.Code = ping_rep_buf[1];
PingReply.Type = ping_rep_buf[2];
PingReply.CheckSum = (ping_rep_buf[3] << 8) + ping_rep_buf[2];
PingReply.ID = (ping_rep_buf[5] << 8) + ping_rep_buf[4];
PingReply.SeqNum = (ping_rep_buf[7] << 8) + ping_rep_buf[6];
for (i = 0; i < len - 8; i++) {
PingReply.Data[i] = ping_rep_buf[8 + i];
}
tmp_checksum = PingReply.CheckSum; /*检查ping回复次数*/
PingReply.CheckSum = 0;
if (tmp_checksum != PingReply.CheckSum) {
KPrintf(" \n CheckSum is in correct %x shold be %x \n", (tmp_checksum),
htons(PingReply.CheckSum));
} else {
}
KPrintf(
" Request from %d.%d.%d.%d ID:%x SeqNum:%x :data size %d bytes\r\n",
(addr[0]), (addr[1]), (addr[2]), (addr[3]), (PingReply.ID),
(PingReply.SeqNum), (rlen + 6));
ping_reply_received = 1; /* 当退出ping回复循环时,设置ping回复标志为1
*/
} else {
KPrintf(" Unkonwn msg. \n");
}
return 0;
}
void wiz_ping_test(int argc, char *argv[]) {
uint32_t tmp_ip[4];
uint8_t target_ip[4];
if (argc >= 2) {
KPrintf("this is ping test: %s\n", argv[1]);
sscanf(argv[1], "%d.%d.%d.%d", &tmp_ip[0], &tmp_ip[1], &tmp_ip[2],
&tmp_ip[3]);
target_ip[0] = (uint8_t)tmp_ip[0];
target_ip[1] = (uint8_t)tmp_ip[1];
target_ip[2] = (uint8_t)tmp_ip[2];
target_ip[3] = (uint8_t)tmp_ip[3];
ping_count(ping_socket, 5, target_ip);
// ping_request(ping_socket, target_ip);
}
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
ping, wiz_ping_test, ping to given addr);
@@ -0,0 +1,35 @@
#ifndef _WIZ_PING_H_
#define _WIZ_PING_H_
#include "socket.h"
#include "w5500.h"
#define PING_BUF_LEN 32
#define PING_REQUEST 8
#define PING_REPLY 0
#define CODE_ZERO 0
#define SOCKET_ERROR 1
#define TIMEOUT_ERROR 2
#define SUCCESS 3
#define REPLY_ERROR 4
typedef struct pingmsg {
uint8_t Type; // 0 - Ping Reply, 8 - Ping Request
uint8_t Code; // Always 0
uint16_t CheckSum; // Check sum
uint16_t ID; // Identification
uint16_t SeqNum; // Sequence Number
int8_t Data[PING_BUF_LEN]; // Ping Data : 1452 = IP RAW MTU -
// sizeof(Type+Code+CheckSum+ID+SeqNum)
} PINGMSGR;
uint8_t ping_count(uint8_t sn, uint16_t pCount, uint8_t *addr);
uint8_t ping_request(uint8_t s, uint8_t *addr);
uint8_t ping_reply(uint8_t s, uint8_t *addr, uint16_t rlen);
void Ethernet_ping_service_deal(uint8_t sn);
#endif
@@ -0,0 +1,862 @@
//****************************************************************************/
//!
//! \file wizchip_conf.c
//! \brief WIZCHIP Config Header File.
//! \version 1.0.1
//! \date 2013/10/21
//! \par Revision history
//! <2015/02/05> Notice
//! The version history is not updated after this point.
//! Download the latest version directly from GitHub. Please visit the
//! our GitHub repository for ioLibrary.
//! >> https://github.com/Wiznet/ioLibrary_Driver
//! <2014/05/01> V1.0.1 Refer to M20140501
//! 1. Explicit type casting in wizchip_bus_readdata() &
//! wizchip_bus_writedata()
// Issued by Mathias ClauBen.
//! uint32_t type converts into ptrdiff_t first. And then recoverting
//! it into uint8_t* For remove the warning when pointer type size is
//! not 32bit. If ptrdiff_t doesn't support in your complier, You
//! should must replace ptrdiff_t into your suitable pointer type.
//! <2013/10/21> 1st Release
//! \author MidnightCow
//! \copyright
//!
//! Copyright (c) 2013, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************/
// A20140501 : for use the type - ptrdiff_t
#include <stddef.h>
//
#include "wizchip_conf.h"
/////////////
// M20150401 : Remove ; in the default callback function such as
// wizchip_cris_enter(), wizchip_cs_select() and etc.
/////////////
/**
* @brief Default function to enable interrupt.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_cris_enter(void) {};
void wizchip_cris_enter(void) {}
/**
* @brief Default function to disable interrupt.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_cris_exit(void) {};
void wizchip_cris_exit(void) {}
/**
* @brief Default function to select chip.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_cs_select(void) {};
void wizchip_cs_select(void) {}
/**
* @brief Default function to deselect chip.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_cs_deselect(void) {};
void wizchip_cs_deselect(void) {}
/**
* @brief Default function to read in direct or indirect interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// M20150601 : Rename the function for integrating with W5300
// uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t
// *)((ptrdiff_t) AddrSel)); }
iodata_t wizchip_bus_readdata(uint32_t AddrSel) {
return *((volatile iodata_t *)((ptrdiff_t)AddrSel));
}
/**
* @brief Default function to write in direct or indirect interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// M20150601 : Rename the function for integrating with W5300
// void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile
// uint8_t*)((ptrdiff_t)AddrSel)) = wb; }
void wizchip_bus_writedata(uint32_t AddrSel, iodata_t wb) {
*((volatile iodata_t *)((ptrdiff_t)AddrSel)) = wb;
}
/**
* @brief Default function to read in SPI interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// uint8_t wizchip_spi_readbyte(void) {return 0;};
uint8_t wizchip_spi_readbyte(void) { return 0; }
/**
* @brief Default function to write in SPI interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_spi_writebyte(uint8_t wb) {};
void wizchip_spi_writebyte(uint8_t wb) {}
/**
* @brief Default function to burst read in SPI interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_spi_readburst(uint8_t* pBuf, uint16_t len) {};
void wizchip_spi_readburst(uint8_t *pBuf, uint16_t len) {}
/**
* @brief Default function to burst write in SPI interface.
* @note This function help not to access wrong address. If you do not describe
* this function or register any functions, null function is called.
*/
// void wizchip_spi_writeburst(uint8_t* pBuf, uint16_t len) {};
void wizchip_spi_writeburst(uint8_t *pBuf, uint16_t len) {}
/**
* @\ref _WIZCHIP instance
*/
//
// M20150401 : For a compiler didnot support a member of structure
// Replace the assignment of struct members with the assingment of
// array
//
/*
_WIZCHIP WIZCHIP =
{
.id = _WIZCHIP_ID_,
.if_mode = _WIZCHIP_IO_MODE_,
.CRIS._enter = wizchip_cris_enter,
.CRIS._exit = wizchip_cris_exit,
.CS._select = wizchip_cs_select,
.CS._deselect = wizchip_cs_deselect,
.IF.BUS._read_byte = wizchip_bus_readbyte,
.IF.BUS._write_byte = wizchip_bus_writebyte
// .IF.SPI._read_byte = wizchip_spi_readbyte,
// .IF.SPI._write_byte = wizchip_spi_writebyte
};
*/
_WIZCHIP WIZCHIP = {_WIZCHIP_IO_MODE_,
_WIZCHIP_ID_,
{wizchip_cris_enter, wizchip_cris_exit},
{wizchip_cs_select, wizchip_cs_deselect},
{
{// M20150601 : Rename the function
// wizchip_bus_readbyte,
// wizchip_bus_writebyte
wizchip_bus_readdata, wizchip_bus_writedata},
}};
static uint8_t _DNS_[4]; // DNS server ip address
static dhcp_mode _DHCP_; // DHCP mode
void reg_wizchip_cris_cbfunc(void (*cris_en)(void), void (*cris_ex)(void)) {
if (!cris_en || !cris_ex) {
WIZCHIP.CRIS._enter = wizchip_cris_enter;
WIZCHIP.CRIS._exit = wizchip_cris_exit;
} else {
WIZCHIP.CRIS._enter = cris_en;
WIZCHIP.CRIS._exit = cris_ex;
}
}
void reg_wizchip_cs_cbfunc(void (*cs_sel)(void), void (*cs_desel)(void)) {
if (!cs_sel || !cs_desel) {
WIZCHIP.CS._select = wizchip_cs_select;
WIZCHIP.CS._deselect = wizchip_cs_deselect;
} else {
WIZCHIP.CS._select = cs_sel;
WIZCHIP.CS._deselect = cs_desel;
}
}
// M20150515 : For integrating with W5300
// void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void
// (*bus_wb)(uint32_t addr, uint8_t wb))
void reg_wizchip_bus_cbfunc(iodata_t (*bus_rb)(uint32_t addr),
void (*bus_wb)(uint32_t addr, iodata_t wb)) {
while (!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_))
;
// M20150601 : Rename call back function for integrating with W5300
/*
if(!bus_rb || !bus_wb)
{
WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte;
WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte;
}
else
{
WIZCHIP.IF.BUS._read_byte = bus_rb;
WIZCHIP.IF.BUS._write_byte = bus_wb;
}
*/
if (!bus_rb || !bus_wb) {
WIZCHIP.IF.BUS._read_data = wizchip_bus_readdata;
WIZCHIP.IF.BUS._write_data = wizchip_bus_writedata;
} else {
WIZCHIP.IF.BUS._read_data = bus_rb;
WIZCHIP.IF.BUS._write_data = bus_wb;
}
}
void reg_wizchip_spi_cbfunc(uint8_t (*spi_rb)(void),
void (*spi_wb)(uint8_t wb)) {
while (!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_))
;
if (!spi_rb || !spi_wb) {
WIZCHIP.IF.SPI._read_byte = wizchip_spi_readbyte;
WIZCHIP.IF.SPI._write_byte = wizchip_spi_writebyte;
} else {
WIZCHIP.IF.SPI._read_byte = spi_rb;
WIZCHIP.IF.SPI._write_byte = spi_wb;
}
}
// 20140626 Eric Added for SPI burst operations
void reg_wizchip_spiburst_cbfunc(void (*spi_rb)(uint8_t *pBuf, uint16_t len),
void (*spi_wb)(uint8_t *pBuf, uint16_t len)) {
while (!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_))
;
if (!spi_rb || !spi_wb) {
WIZCHIP.IF.SPI._read_burst = wizchip_spi_readburst;
WIZCHIP.IF.SPI._write_burst = wizchip_spi_writeburst;
} else {
WIZCHIP.IF.SPI._read_burst = spi_rb;
WIZCHIP.IF.SPI._write_burst = spi_wb;
}
}
int8_t ctlwizchip(ctlwizchip_type cwtype, void *arg) {
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
uint8_t tmp = 0;
#endif
uint8_t *ptmp[2] = {0, 0};
switch (cwtype) {
case CW_RESET_WIZCHIP:
wizchip_sw_reset();
break;
case CW_INIT_WIZCHIP:
if (arg != 0) {
ptmp[0] = (uint8_t *)arg;
ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_;
}
return wizchip_init(ptmp[0], ptmp[1]);
case CW_CLR_INTERRUPT:
wizchip_clrinterrupt(*((intr_kind *)arg));
break;
case CW_GET_INTERRUPT:
*((intr_kind *)arg) = wizchip_getinterrupt();
break;
case CW_SET_INTRMASK:
wizchip_setinterruptmask(*((intr_kind *)arg));
break;
case CW_GET_INTRMASK:
*((intr_kind *)arg) = wizchip_getinterruptmask();
break;
// M20150601 : This can be supported by W5200, W5500
//#if _WIZCHIP_ > W5100
#if (_WIZCHIP_ == W5200 || _WIZCHIP_ == W5500)
case CW_SET_INTRTIME:
setINTLEVEL(*(uint16_t *)arg);
break;
case CW_GET_INTRTIME:
*(uint16_t *)arg = getINTLEVEL();
break;
#endif
case CW_GET_ID:
((uint8_t *)arg)[0] = WIZCHIP.id[0];
((uint8_t *)arg)[1] = WIZCHIP.id[1];
((uint8_t *)arg)[2] = WIZCHIP.id[2];
((uint8_t *)arg)[3] = WIZCHIP.id[3];
((uint8_t *)arg)[4] = WIZCHIP.id[4];
((uint8_t *)arg)[5] = WIZCHIP.id[5];
((uint8_t *)arg)[6] = 0;
break;
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5500
case CW_RESET_PHY:
wizphy_reset();
break;
case CW_SET_PHYCONF:
wizphy_setphyconf((wiz_PhyConf *)arg);
break;
case CW_GET_PHYCONF:
wizphy_getphyconf((wiz_PhyConf *)arg);
break;
case CW_GET_PHYSTATUS:
break;
case CW_SET_PHYPOWMODE:
return wizphy_setphypmode(*(uint8_t *)arg);
#endif
#if _WIZCHIP_ == W5100S || _WIZCHIP_ == W5200 || _WIZCHIP_ == W5500
case CW_GET_PHYPOWMODE:
tmp = wizphy_getphypmode();
if ((int8_t)tmp == -1)
return -1;
*(uint8_t *)arg = tmp;
break;
case CW_GET_PHYLINK:
tmp = wizphy_getphylink();
if ((int8_t)tmp == -1)
return -1;
*(uint8_t *)arg = tmp;
break;
#endif
default:
return -1;
}
return 0;
}
int8_t ctlnetwork(ctlnetwork_type cntype, void *arg) {
switch (cntype) {
case CN_SET_NETINFO:
wizchip_setnetinfo((wiz_NetInfo *)arg);
break;
case CN_GET_NETINFO:
wizchip_getnetinfo((wiz_NetInfo *)arg);
break;
case CN_SET_NETMODE:
return wizchip_setnetmode(*(netmode_type *)arg);
case CN_GET_NETMODE:
*(netmode_type *)arg = wizchip_getnetmode();
break;
case CN_SET_TIMEOUT:
wizchip_settimeout((wiz_NetTimeout *)arg);
break;
case CN_GET_TIMEOUT:
wizchip_gettimeout((wiz_NetTimeout *)arg);
break;
default:
return -1;
}
return 0;
}
void wizchip_sw_reset(void) {
uint8_t gw[4], sn[4], sip[4];
uint8_t mac[6];
// A20150601
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
uint16_t mr = (uint16_t)getMR();
setMR(mr | MR_IND);
#endif
//
getSHAR(mac);
getGAR(gw);
getSUBR(sn);
getSIPR(sip);
setMR(MR_RST);
getMR(); // for delay
// A2015051 : For indirect bus mode
#if _WIZCHIP_IO_MODE_ == _WIZCHIP_IO_MODE_BUS_INDIR_
setMR(mr | MR_IND);
#endif
//
setSHAR(mac);
setGAR(gw);
setSUBR(sn);
setSIPR(sip);
}
int8_t wizchip_init(uint8_t *txsize, uint8_t *rxsize) {
int8_t i;
#if _WIZCHIP_ < W5200
int8_t j;
#endif
int8_t tmp = 0;
wizchip_sw_reset();
if (txsize) {
tmp = 0;
// M20150601 : For integrating with W5300
#if _WIZCHIP_ == W5300
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
if (txsize[i] >= 64)
return -1; // No use 64KB even if W5300 support max 64KB memory
// allocation
tmp += txsize[i];
if (tmp > 128)
return -1;
}
if (tmp % 8)
return -1;
#else
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
tmp += txsize[i];
#if _WIZCHIP_ < W5200 // 2016.10.28 peter add condition for w5100 and w5100s
if (tmp > 8)
return -1;
#else
if (tmp > 16)
return -1;
#endif
}
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
#if _WIZCHIP_ < W5200 // 2016.10.28 peter add condition for w5100
j = 0;
while ((txsize[i] >> j != 1) && (txsize[i] != 0)) {
j++;
}
setSn_TXBUF_SIZE(i, j);
#else
setSn_TXBUF_SIZE(i, txsize[i]);
#endif
}
#endif
}
if (rxsize) {
tmp = 0;
#if _WIZCHIP_ == W5300
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
if (rxsize[i] >= 64)
return -1; // No use 64KB even if W5300 support max 64KB memory
// allocation
tmp += rxsize[i];
if (tmp > 128)
return -1;
}
if (tmp % 8)
return -1;
#else
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
tmp += rxsize[i];
#if _WIZCHIP_ < W5200 // 2016.10.28 peter add condition for w5100 and w5100s
if (tmp > 8)
return -1;
#else
if (tmp > 16)
return -1;
#endif
}
for (i = 0; i < _WIZCHIP_SOCK_NUM_; i++) {
#if _WIZCHIP_ < W5200 // add condition for w5100
j = 0;
while ((rxsize[i] >> j != 1) && (txsize[i] != 0)) {
j++;
}
setSn_RXBUF_SIZE(i, j);
#else
setSn_RXBUF_SIZE(i, rxsize[i]);
#endif
}
#endif
}
return 0;
}
void wizchip_clrinterrupt(intr_kind intr) {
uint8_t ir = (uint8_t)intr;
uint8_t sir = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < W5500
ir |= (1 << 4); // IK_WOL
#endif
#if _WIZCHIP_ == W5200
ir |= (1 << 6);
#endif
#if _WIZCHIP_ < W5200
sir &= 0x0F;
#endif
#if _WIZCHIP_ <= W5100S
ir |= sir;
setIR(ir);
// A20150601 : For integrating with W5300
#elif _WIZCHIP_ == W5300
setIR(((((uint16_t)ir) << 8) | (((uint16_t)sir) & 0x00FF)));
#else
setIR(ir);
// M20200227 : For clear
// setSIR(sir);
for (ir = 0; ir < 8; ir++) {
if (sir & (0x01 << ir))
setSn_IR(ir, 0xff);
}
#endif
}
intr_kind wizchip_getinterrupt(void) {
uint8_t ir = 0;
uint8_t sir = 0;
uint16_t ret = 0;
#if _WIZCHIP_ <= W5100S
ir = getIR();
sir = ir & 0x0F;
// A20150601 : For integrating with W5300
#elif _WIZCHIP_ == W5300
ret = getIR();
ir = (uint8_t)(ret >> 8);
sir = (uint8_t)ret;
#else
ir = getIR();
sir = getSIR();
#endif
// M20150601 : For Integrating with W5300
//#if _WIZCHIP_ < W5500
#if _WIZCHIP_ < W5200
ir &= ~(1 << 4); // IK_WOL
#endif
#if _WIZCHIP_ == W5200
ir &= ~(1 << 6);
#endif
ret = sir;
ret = (ret << 8) + ir;
return (intr_kind)ret;
}
void wizchip_setinterruptmask(intr_kind intr) {
uint8_t imr = (uint8_t)intr;
uint8_t simr = (uint8_t)((uint16_t)intr >> 8);
#if _WIZCHIP_ < W5500
imr &= ~(1 << 4); // IK_WOL
#endif
#if _WIZCHIP_ == W5200
imr &= ~(1 << 6);
#endif
#if _WIZCHIP_ < W5200
simr &= 0x0F;
imr |= simr;
setIMR(imr);
// A20150601 : For integrating with W5300
#elif _WIZCHIP_ == W5300
setIMR(((((uint16_t)imr) << 8) | (((uint16_t)simr) & 0x00FF)));
#else
setIMR(imr);
setSIMR(simr);
#endif
}
intr_kind wizchip_getinterruptmask(void) {
uint8_t imr = 0;
uint8_t simr = 0;
uint16_t ret = 0;
#if _WIZCHIP_ < W5200
imr = getIMR();
simr = imr & 0x0F;
// A20150601 : For integrating with W5300
#elif _WIZCHIP_ == W5300
ret = getIMR();
imr = (uint8_t)(ret >> 8);
simr = (uint8_t)ret;
#else
imr = getIMR();
simr = getSIMR();
#endif
#if _WIZCHIP_ < W5500
imr &= ~(1 << 4); // IK_WOL
#endif
#if _WIZCHIP_ == W5200
imr &= ~(1 << 6); // IK_DEST_UNREACH
#endif
ret = simr;
ret = (ret << 8) + imr;
return (intr_kind)ret;
}
int8_t wizphy_getphylink(void) {
int8_t tmp = PHY_LINK_OFF;
#if _WIZCHIP_ == W5100S
if (getPHYSR() & PHYSR_LNK)
tmp = PHY_LINK_ON;
#elif _WIZCHIP_ == W5200
if (getPHYSTATUS() & PHYSTATUS_LINK)
tmp = PHY_LINK_ON;
#elif _WIZCHIP_ == W5500
if (getPHYCFGR() & PHYCFGR_LNK_ON)
tmp = PHY_LINK_ON;
#else
tmp = -1;
#endif
return tmp;
}
#if _WIZCHIP_ > W5100
int8_t wizphy_getphypmode(void) {
int8_t tmp = 0;
#if _WIZCHIP_ == W5200
if (getPHYSTATUS() & PHYSTATUS_POWERDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#elif _WIZCHIP_ == 5500
if ((getPHYCFGR() & PHYCFGR_OPMDC_ALLA) == PHYCFGR_OPMDC_PDOWN)
tmp = PHY_POWER_DOWN;
else
tmp = PHY_POWER_NORM;
#else
tmp = -1;
#endif
return tmp;
}
#endif
#if _WIZCHIP_ == W5100S
void wizphy_reset(void) {
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
tmp |= BMCR_RESET;
wiz_mdio_write(PHYMDIO_BMCR, tmp);
while (wiz_mdio_read(PHYMDIO_BMCR) & BMCR_RESET) {
}
}
void wizphy_setphyconf(wiz_PhyConf *phyconf) {
uint16_t tmp = wiz_mdio_read(PHYMDIO_BMCR);
if (phyconf->mode == PHY_MODE_AUTONEGO)
tmp |= BMCR_AUTONEGO;
else {
tmp &= ~BMCR_AUTONEGO;
if (phyconf->duplex == PHY_DUPLEX_FULL) {
tmp |= BMCR_DUP;
} else {
tmp &= ~BMCR_DUP;
}
if (phyconf->speed == PHY_SPEED_100) {
tmp |= BMCR_SPEED;
} else {
tmp &= ~BMCR_SPEED;
}
}
wiz_mdio_write(PHYMDIO_BMCR, tmp);
}
void wizphy_getphyconf(wiz_PhyConf *phyconf) {
uint16_t tmp = 0;
tmp = wiz_mdio_read(PHYMDIO_BMCR);
phyconf->by = PHY_CONFBY_SW;
if (tmp & BMCR_AUTONEGO) {
phyconf->mode = PHY_MODE_AUTONEGO;
} else {
phyconf->mode = PHY_MODE_MANUAL;
if (tmp & BMCR_DUP)
phyconf->duplex = PHY_DUPLEX_FULL;
else
phyconf->duplex = PHY_DUPLEX_HALF;
if (tmp & BMCR_SPEED)
phyconf->speed = PHY_SPEED_100;
else
phyconf->speed = PHY_SPEED_10;
}
}
int8_t wizphy_setphypmode(uint8_t pmode) {
uint16_t tmp = 0;
tmp = wiz_mdio_read(PHYMDIO_BMCR);
if (pmode == PHY_POWER_DOWN) {
tmp |= BMCR_PWDN;
} else {
tmp &= ~BMCR_PWDN;
}
wiz_mdio_write(PHYMDIO_BMCR, tmp);
tmp = wiz_mdio_read(PHYMDIO_BMCR);
if (pmode == PHY_POWER_DOWN) {
if (tmp & BMCR_PWDN)
return 0;
} else {
if ((tmp & BMCR_PWDN) != BMCR_PWDN)
return 0;
}
return -1;
}
#endif
#if _WIZCHIP_ == W5500
void wizphy_reset(void) {
uint8_t tmp = getPHYCFGR();
tmp &= PHYCFGR_RST;
setPHYCFGR(tmp);
tmp = getPHYCFGR();
tmp |= ~PHYCFGR_RST;
setPHYCFGR(tmp);
}
void wizphy_setphyconf(wiz_PhyConf *phyconf) {
uint8_t tmp = 0;
if (phyconf->by == PHY_CONFBY_SW)
tmp |= PHYCFGR_OPMD;
else
tmp &= ~PHYCFGR_OPMD;
if (phyconf->mode == PHY_MODE_AUTONEGO)
tmp |= PHYCFGR_OPMDC_ALLA;
else {
if (phyconf->duplex == PHY_DUPLEX_FULL) {
if (phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100F;
else
tmp |= PHYCFGR_OPMDC_10F;
} else {
if (phyconf->speed == PHY_SPEED_100)
tmp |= PHYCFGR_OPMDC_100H;
else
tmp |= PHYCFGR_OPMDC_10H;
}
}
setPHYCFGR(tmp);
wizphy_reset();
}
void wizphy_getphyconf(wiz_PhyConf *phyconf) {
uint8_t tmp = 0;
tmp = getPHYCFGR();
phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW;
switch (tmp & PHYCFGR_OPMDC_ALLA) {
case PHYCFGR_OPMDC_ALLA:
case PHYCFGR_OPMDC_100FA:
phyconf->mode = PHY_MODE_AUTONEGO;
break;
default:
phyconf->mode = PHY_MODE_MANUAL;
break;
}
switch (tmp & PHYCFGR_OPMDC_ALLA) {
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_100H:
phyconf->speed = PHY_SPEED_100;
break;
default:
phyconf->speed = PHY_SPEED_10;
break;
}
switch (tmp & PHYCFGR_OPMDC_ALLA) {
case PHYCFGR_OPMDC_100FA:
case PHYCFGR_OPMDC_100F:
case PHYCFGR_OPMDC_10F:
phyconf->duplex = PHY_DUPLEX_FULL;
break;
default:
phyconf->duplex = PHY_DUPLEX_HALF;
break;
}
}
void wizphy_getphystat(wiz_PhyConf *phyconf) {
uint8_t tmp = getPHYCFGR();
phyconf->duplex =
(tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10;
}
int8_t wizphy_setphypmode(uint8_t pmode) {
uint8_t tmp = 0;
tmp = getPHYCFGR();
if ((tmp & PHYCFGR_OPMD) == 0)
return -1;
tmp &= ~PHYCFGR_OPMDC_ALLA;
if (pmode == PHY_POWER_DOWN)
tmp |= PHYCFGR_OPMDC_PDOWN;
else
tmp |= PHYCFGR_OPMDC_ALLA;
setPHYCFGR(tmp);
wizphy_reset();
tmp = getPHYCFGR();
if (pmode == PHY_POWER_DOWN) {
if (tmp & PHYCFGR_OPMDC_PDOWN)
return 0;
} else {
if (tmp & PHYCFGR_OPMDC_ALLA)
return 0;
}
return -1;
}
#endif
void wizchip_setnetinfo(wiz_NetInfo *pnetinfo) {
setSHAR(pnetinfo->mac);
setGAR(pnetinfo->gw);
setSUBR(pnetinfo->sn);
setSIPR(pnetinfo->ip);
_DNS_[0] = pnetinfo->dns[0];
_DNS_[1] = pnetinfo->dns[1];
_DNS_[2] = pnetinfo->dns[2];
_DNS_[3] = pnetinfo->dns[3];
_DHCP_ = pnetinfo->dhcp;
}
void wizchip_getnetinfo(wiz_NetInfo *pnetinfo) {
getSHAR(pnetinfo->mac);
getGAR(pnetinfo->gw);
getSUBR(pnetinfo->sn);
getSIPR(pnetinfo->ip);
pnetinfo->dns[0] = _DNS_[0];
pnetinfo->dns[1] = _DNS_[1];
pnetinfo->dns[2] = _DNS_[2];
pnetinfo->dns[3] = _DNS_[3];
pnetinfo->dhcp = _DHCP_;
}
int8_t wizchip_setnetmode(netmode_type netmode) {
uint8_t tmp = 0;
#if _WIZCHIP_ != W5500
if (netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK))
return -1;
#else
if (netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP))
return -1;
#endif
tmp = getMR();
tmp |= (uint8_t)netmode;
setMR(tmp);
return 0;
}
netmode_type wizchip_getnetmode(void) { return (netmode_type)getMR(); }
void wizchip_settimeout(wiz_NetTimeout *nettime) {
setRCR(nettime->retry_cnt);
setRTR(nettime->time_100us);
}
void wizchip_gettimeout(wiz_NetTimeout *nettime) {
nettime->retry_cnt = getRCR();
nettime->time_100us = getRTR();
}