Trying to support lwip with w5500.

This commit is contained in:
涂煜洋 2023-08-25 13:43:11 +08:00
parent a5a809aa0a
commit 8b32c2f4ed
12 changed files with 562 additions and 12 deletions

View File

@ -19,7 +19,7 @@ export CXXFLAGS := -mcmodel=medany -march=rv64imafdc -mabi=lp64d -fno-common -ff
export CROSS_COMPILE ?=/opt/gnu-mcu-eclipse/riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-
export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO
export DEFINES := -DHAVE_CCONFIG_H -DHAVE_SIGINFO -DRISCV_LWIP
export ARCH = risc-v
export MCU = k210

View File

@ -2,6 +2,7 @@
config BSP_USING_W5500
bool "Using w5500"
select BSP_USING_LWIP
default y
config BSP_WIZ_RST_PIN
@ -15,3 +16,8 @@ config BSP_WIZ_INT_PIN
config BSP_WIZ_USE_IPERF
bool "Using iperf"
default y
menuconfig BSP_USING_LWIP
bool "Using LwIP device"
default n
select RESOURCES_LWIP

View File

@ -1,3 +1,4 @@
SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c connect_w5500_test.c wiz_iperf.c
# SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c wiz_ping.c connect_w5500_test.c wiz_iperf.c
SRC_FILES := socket.c connect_w5500.c w5500.c wizchip_conf.c spi_interface.c connect_w5500_test.c w5x00_lwip.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -14,6 +14,8 @@
#include "socket.h"
#include "w5500.h"
#include "connect_ethernet.h"
#define SPI_LORA_FREQUENCY 10000000
// spi operations
@ -258,6 +260,27 @@ int HwWiznetInit(void) {
return ERROR;
}
extern uint8_t wiz_mac[6];
setSHAR(wiz_mac);
ctlwizchip(CW_RESET_PHY, 0);
setSn_MR(0, Sn_MR_MFEN | Sn_MR_MACRAW | Sn_MR_MIP6B | Sn_MR_MMB);
// setSn_RXBUF_SIZE(0, 16);
// setSn_TXBUF_SIZE(0, 16);
#define SOCK_ANY_PORT_NUM 0xC000
wiz_socket(0, Sn_MR_MACRAW, SOCK_ANY_PORT_NUM, 0x00);
// setSn_CR(0, Sn_CR_OPEN);
// setSn_CR(0, Sn_CR_CONNECT);
uint8_t sock_sr = 0;
while (1) {
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] sock_sr: %x, MACRAW: %x\n", __func__, sock_sr = getSn_SR(0), SOCK_MACRAW));
if (sock_sr == SOCK_MACRAW) {
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("Socket 0 MACRAW mdoe established\r\n"));
break;
}
}
network_init();
return EOK;

View File

@ -0,0 +1,370 @@
/**
* Copyright (c) 2022 WIZnet Co.,Ltd
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/**
* ----------------------------------------------------------------------------------------------------
* Includes
* ----------------------------------------------------------------------------------------------------
*/
#include <stdio.h>
#include "connect_ethernet.h"
#include "socket.h"
#include "netif/etharp.h"
#include <xs_kdbg.h>
#include <xizi.h>
/**
* ----------------------------------------------------------------------------------------------------
* Macros
* ----------------------------------------------------------------------------------------------------
*/
/**
* ----------------------------------------------------------------------------------------------------
* Variables
* ----------------------------------------------------------------------------------------------------
*/
uint8_t wiz_mac[6] = { 0x00, 0x08, 0xDC, 0x12, 0x34, 0x56 };
static uint8_t tx_frame[1542];
static const uint32_t ethernet_polynomial_le = 0xedb88320U;
/**
* ----------------------------------------------------------------------------------------------------
* Functions
* ----------------------------------------------------------------------------------------------------
*/
void* ethernetif_config_enet_set(uint8_t enet_port)
{
return NONE;
}
void Time_Update_LwIP(void)
{
// no need to do
}
int32_t send_lwip(uint8_t sn, uint8_t* buf, uint16_t len)
{
uint8_t tmp = 0;
uint16_t freesize = 0;
tmp = getSn_SR(sn);
// freesize = getSn_TxMAX(sn);
// freesize = getSn_TXBUF_SIZE(sn);
freesize = getSn_TX_FSR(sn);
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] sending len: %d, free size: %d\n", __func__, len, freesize));
if (len > freesize)
len = freesize; // check size not to exceed MAX size.
wiz_send_data(sn, buf, len);
setSn_CR(sn, Sn_CR_SEND);
while (getSn_CR(sn))
;
while (1) {
uint8_t IRtemp = getSn_IR(sn);
if (IRtemp & Sn_IR_SENDOK) {
setSn_IR(sn, Sn_IR_SENDOK);
// printf("Packet sent ok\n");
break;
} else if (IRtemp & Sn_IR_TIMEOUT) {
setSn_IR(sn, Sn_IR_TIMEOUT);
// printf("Socket is closed\n");
// There was a timeout
return -1;
}
}
return (int32_t)len;
}
int32_t recv_lwip(uint8_t sn, uint8_t* buf, uint16_t len)
{
uint8_t head[2];
uint16_t pack_len = 0;
pack_len = getSn_RX_RSR(sn);
if (pack_len > 0) {
wiz_recv_data(sn, head, 2);
setSn_CR(sn, Sn_CR_RECV);
// byte size of data packet (2byte)
pack_len = head[0];
pack_len = (pack_len << 8) + head[1];
pack_len -= 2;
if (pack_len > len) {
// Packet is bigger than buffer - drop the packet
// wiz_recv_ignore(sn, pack_len);
// setSn_CR(sn, Sn_CR_RECV);
// return 0;
pack_len = len;
}
wiz_recv_data(sn, buf, pack_len); // data copy
setSn_CR(sn, Sn_CR_RECV);
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] recved len: %d, len: %d\n", __func__, pack_len, len));
}
return (int32_t)pack_len;
}
err_t netif_output(struct netif* netif, struct pbuf* p)
{
uint32_t send_len = 0;
uint32_t tot_len = 0;
memset(tx_frame, 0x00, sizeof(tx_frame));
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] pbuf len: %d, totlen: %d\n", __func__, p->len, p->tot_len));
for (struct pbuf* q = p; q != NULL; q = q->next) {
memcpy(tx_frame + tot_len, q->payload, q->len);
tot_len += q->len;
if (q->len == q->tot_len) {
break;
}
}
if (tot_len < 60) {
// pad
tot_len = 60;
}
uint32_t crc = ethernet_frame_crc(tx_frame, tot_len);
send_len = send_lwip(0, tx_frame, tot_len);
return ERR_OK;
}
static uint16_t wiz_sendFrame(uint8_t* buf, uint16_t len)
{
// Wait for space in the transmit buffer
// while (1) {
// SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] looping for freesize, sock state: %x\n", __func__, getSn_SR(0)));
// uint16_t freesize = getSn_TX_FSR(0);
// if (len <= freesize) {
// break;
// }
// };
wiz_send_data(0, buf, len);
setSn_CR(0, Sn_CR_SEND);
while (1) {
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] looping for sendok\n", __func__));
uint8_t tmp = getSn_IR(0);
if (tmp & Sn_IR_SENDOK) {
setSn_IR(0, Sn_IR_SENDOK);
// Packet sent ok
break;
} else if (tmp & Sn_IR_TIMEOUT) {
setSn_IR(0, Sn_IR_TIMEOUT);
// There was a timeout
return -1;
}
}
return len;
}
// void ethernetif_input(void* netif_arg)
// {
// struct netif* netif = (struct netif*)netif_arg;
// struct pbuf* p;
// uint16_t pack_len = 0;
// uint8_t* pack = malloc(ETHERNET_MTU);
// while (1) {
// wiz_getsockopt(SOCKET_MACRAW, SO_RECVBUF, &pack_len);
// if (pack_len > 0) {
// pack_len = recv_lwip(SOCKET_MACRAW, (uint8_t*)pack, pack_len);
// if (pack_len) {
// p = pbuf_alloc(PBUF_RAW, pack_len, PBUF_POOL);
// pbuf_take(p, pack, pack_len);
// free(pack);
// pack = malloc(ETHERNET_MTU);
// } else {
// printf(" No packet received\n");
// }
// if (pack_len && p != NULL) {
// LINK_STATS_INC(link.recv);
// if (netif->input(p, netif) != ERR_OK) {
// pbuf_free(p);
// }
// }
// }
// }
// }
void netif_link_callback(struct netif* netif)
{
printf("netif link status changed %s\n", netif_is_link_up(netif) ? "up" : "down");
}
void netif_status_callback(struct netif* netif)
{
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
}
static void wiz_transmit_pbuf(struct pbuf* p)
{
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("+++++++"));
uint16_t freeSize = getSn_TX_FSR(0);
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] max tx len: %d, current tx len: %d\n", __func__, getSn_TxMAX(0), freeSize));
uint16_t length = p->tot_len;
if (freeSize < length) {
/* TODO: Handle insufficent space in buffer */
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] max tx len: %d, current tx len: %d\n", __func__, getSn_TxMAX(0), freeSize));
setSn_CR(0, Sn_CR_SEND);
return;
}
while (1) {
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] pbuf len: %d, totlen: %d\n", __func__, p->len, p->tot_len));
// wiz_send_data(0, p->payload, p->len);
wiz_sendFrame((uint8_t*)p->payload, p->len);
if (p->len == p->tot_len)
break;
p = p->next;
}
setSn_CR(0, Sn_CR_SEND);
}
static int wiz_read_receive_pbuf(struct pbuf** buf)
{
// uint8_t header[6];
uint16_t length;
// uint16_t readlen;
uint16_t framelen;
// struct pbuf * p;
if (*buf != NULL)
return 1;
// uint16_t rxRd = getSn_RX_RD(0);
length = getSn_RX_RSR(0);
if (length < 4) {
/* This could be indicative of a crashed (brown-outed?) controller */
goto end;
}
wiz_recv_data(0, (uint8_t*)&framelen, 2);
setSn_CR(0, Sn_CR_RECV);
//__bswap16(framelen); //!< didn't work for me
framelen = (framelen << 8) | (framelen >> 8);
/* workaround for https://savannah.nongnu.org/bugs/index.php?50040 */
if (framelen > 32000) {
wiz_recv_ignore(0, framelen);
setSn_CR(0, Sn_CR_RECV);
goto end;
}
framelen -= 2;
*buf = pbuf_alloc(PBUF_RAW, (framelen), PBUF_RAM);
if (*buf == NULL) {
goto end;
}
wiz_recv_data(0, (*buf)->payload, framelen);
setSn_CR(0, Sn_CR_RECV);
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] recved data: framelen: %d\n", __func__, framelen));
end:
return (*buf == NULL) ? 2 : 0;
}
void spi_if_clr(void)
{
setSn_IR(0, 0x1F);
setSIR(0);
}
void ethernetif_input(void* netif_arg)
{
struct netif* netif = (struct netif*)netif_arg;
struct pbuf* p = NULL;
uint8_t res = 0;
uint16_t epktcnt;
for (;;) {
spi_if_clr();
p = NULL;
res = wiz_read_receive_pbuf(&p);
if (p != NULL) {
LWIP_DEBUGF(NETIF_DEBUG, ("incoming: %d packages, first read into %x\n", epktcnt, (uintptr_t)(p)));
if (ERR_OK != netif->input(p, netif)) {
pbuf_free(p);
p = NULL;
} else {
p = NULL;
}
} else {
// LWIP_DEBUGF(NETIF_DEBUG, ("didn't receive.\n"));
}
}
}
static err_t spi_if_linkoutput(struct netif* netif, struct pbuf* p)
{
while (!(getSn_SR(0) & SOCK_MACRAW))
; /* TODO: Implement wait timeout */
SYS_KDEBUG_LOG(WIZNET_DEBUG, ("[%s] data output, len: %d\n", __func__, p->tot_len));
wiz_transmit_pbuf(p);
LWIP_DEBUGF(NETIF_DEBUG, ("sent %d bytes.\n", p->tot_len));
/* TODO: Set up result value */
return ERR_OK;
}
err_t netif_initialize(struct netif* netif)
{
netif->linkoutput = spi_if_linkoutput;
// netif->linkoutput = netif_output;
netif->output = etharp_output;
netif->mtu = ETHERNET_MTU;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
SMEMCPY(netif->hwaddr, wiz_mac, sizeof(netif->hwaddr));
netif->hwaddr_len = sizeof(netif->hwaddr);
netif->name[0] = 'e';
netif->name[1] = '0';
return ERR_OK;
}
static uint32_t ethernet_frame_crc(const uint8_t* data, int length)
{
uint32_t crc = 0xffffffff; /* Initial value. */
while (--length >= 0) {
uint8_t current_octet = *data++;
for (int bit = 8; --bit >= 0; current_octet >>= 1) {
if ((crc ^ current_octet) & 1) {
crc >>= 1;
crc ^= ethernet_polynomial_le;
} else
crc >>= 1;
}
}
return ~crc;
}

View File

@ -304,7 +304,7 @@ __exit:
if (recv_data) free(recv_data);
}
void iperf_usage(void)
static void iperf_usage(void)
{
KPrintf("Usage: iperf [-s|-c host] [options] [multi-threaded]\n");
KPrintf(" iperf [-h|--stop]\n");
@ -326,7 +326,7 @@ void iperf_usage(void)
return;
}
int iperf(int argc, char **argv)
int wiz_iperf(int argc, char** argv)
{
int mode = 0; /* server mode */
char *host = NULL;
@ -460,6 +460,6 @@ __usage:
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
iperf, iperf,
iperf throughput test);
wiz_iperf, wiz_iperf,
iperf throughput test);
#endif

View File

@ -0,0 +1,118 @@
/**
* Copyright (c) 2022 WIZnet Co.,Ltd
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _W5x00_LWIP_H_
#define _W5x00_LWIP_H_
/**
* ----------------------------------------------------------------------------------------------------
* Includes
* ----------------------------------------------------------------------------------------------------
*/
#include "lwip/netif.h"
/**
* ----------------------------------------------------------------------------------------------------
* Macros
* ----------------------------------------------------------------------------------------------------
*/
/* LWIP */
#define ETHERNET_MTU 1500
#define SOCKET_MACRAW 0
/**
* ----------------------------------------------------------------------------------------------------
* Variables
* ----------------------------------------------------------------------------------------------------
*/
/**
* ----------------------------------------------------------------------------------------------------
* Functions
* ----------------------------------------------------------------------------------------------------
*/
/*! \brief send an ethernet packet
* \ingroup w5x00_lwip
*
* It is used to send outgoing data to the socket.
*
* \param sn socket number
* \param buf a pointer to the data to send
* \param len the length of data in packet
* \return he sent data size
*/
int32_t send_lwip(uint8_t sn, uint8_t* buf, uint16_t len);
/*! \brief read an ethernet packet
* \ingroup w5x00_lwip
*
* It is used to read incoming data from the socket.
*
* \param sn socket number
* \param buf a pointer buffer to read incoming data
* \param len the length of the data in the packet
* \return the real received data size
*/
int32_t recv_lwip(uint8_t sn, uint8_t* buf, uint16_t len);
/*! \brief callback function
* \ingroup w5x00_lwip
*
* This function is called by ethernet_output() when it wants
* to send a packet on the interface. This function outputs
* the pbuf as-is on the link medium.
*
* \param netif a pre-allocated netif structure
* \param p main packet buffer struct
* \return ERR_OK if data was sent.
*/
err_t netif_output(struct netif* netif, struct pbuf* p);
/*! \brief callback function
* \ingroup w5x00_lwip
*
* Callback function for link.
*
* \param netif a pre-allocated netif structure
*/
void netif_link_callback(struct netif* netif);
/*! \brief callback function
* \ingroup w5x00_lwip
*
* Callback function for status.
*
* \param netif a pre-allocated netif structure
*/
void netif_status_callback(struct netif* netif);
/*! \brief callback function
* \ingroup w5x00_lwip
*
* Callback function that initializes the interface.
*
* \param netif a pre-allocated netif structure
* \return ERR_OK if Network interface initialized
*/
err_t netif_initialize(struct netif* netif);
/*! \brief ethernet frame cyclic redundancy check
* \ingroup w5x00_lwip
*
* Perform cyclic redundancy check on ethernet frame
*
* \param data a pointer to the ethernet frame
* \param length the total length of ethernet frame
* \return an ethernet frame cyclic redundancy check result value
*/
static uint32_t ethernet_frame_crc(const uint8_t* data, int length);
void ethernetif_input(void* netif_arg);
void* ethernetif_config_enet_set(uint8_t enet_port);
void Time_Update_LwIP(void);
#define NETIF_ENET0_INIT_FUNC netif_initialize
#endif /* _W5x00_LWIP_H_ */

View File

@ -46,6 +46,7 @@ extern "C" {
#define FILESYS_DEBUG 0
#define NETDEV_DEBUG 0
#define WEBNET_DEBUG 0
#define WIZNET_DEBUG 1
#define SYS_KDEBUG_LOG(section, information) \
do { \

View File

@ -112,6 +112,21 @@ KERNELPATHS += \
-I$(BSP_ROOT)/third_party_driver/drivers \
-I$(BSP_ROOT)/third_party_driver/lcd \
-I$(KERNEL_ROOT)/include #
ifeq ($(CONFIG_RESOURCES_LWIP),y)
KERNELPATHS += \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/compat \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/netif \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/apps \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
endif
endif
ifeq ($(BSP_ROOT),$(KERNEL_ROOT)/board/kd233)

View File

@ -35,6 +35,11 @@
/* ---------- Debug options ---------- */
#ifndef LWIP_DEBUG
#define LWIP_DEBUG 1
// #define LWIP_SOCKET_DEBUG
// #define LWIP_TCPIP_DEBUG
// #define LWIP_TCP_INPUT_DEBUG
// #define LWIP_TCP_OUTPUT_DEBUG
// #define LWIP_NETIF_DEBUG
#endif
#ifdef LWIP_DEBUG
@ -219,6 +224,7 @@
#define LWIP_SOCKET_SELECT 1
#define LWIP_SOCKET_POLL 1
#define LWIP_DHCP_DOES_ACD_CHECK 0
/**
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
* critical regions during buffer allocation, deallocation and memory
@ -242,7 +248,11 @@
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
#ifndef RISCV_LWIP
#define MEM_ALIGNMENT 4
#else
#define MEM_ALIGNMENT 8
#endif
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
@ -287,7 +297,7 @@ a lot of data that needs to be copied, this should be set high. */
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 1
#define TCP_QUEUE_OOSEQ 0
/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
@ -442,7 +452,11 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
/**
* LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
*/
#ifndef RISCV_LWIP
#define LWIP_NETCONN 1
#else
#define LWIP_NETCONN 0
#endif
/*
------------------------------------

View File

@ -338,11 +338,11 @@ void lwip_config_input(struct netif* net)
th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 30);
if (th_id >= 0) {
lw_print("%s %d successfully!\n", __func__, th_id);
} else {
lw_print("%s failed!\n", __func__);
}
// if (th_id >= 0) {
// lw_print("%s %d successfully!\n", __func__, th_id);
// } else {
// lw_print("%s failed!\n", __func__);
// }
}
void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw)

View File

@ -200,7 +200,9 @@ typedef uintptr_t mem_ptr_t;
#include <unistd.h>
#endif
#else /* SSIZE_MAX */
#ifndef RISCV_LWIP
typedef int ssize_t;
#endif
#define SSIZE_MAX INT_MAX
#endif /* SSIZE_MAX */