From 0808a83a8e24cb36ecd53c96be8f7ba745734505 Mon Sep 17 00:00:00 2001 From: wlyu Date: Fri, 16 Sep 2022 15:12:02 +0800 Subject: [PATCH] support ethernet with w5500 --- .../aiit_board/xidatong-riscv64/Kconfig | 4 + .../configs/{ec200nsh => 4gnsh}/defconfig | 0 .../xidatong-riscv64/configs/netnsh/defconfig | 61 ++ .../configs/wifinsh/defconfig | 78 ++ .../aiit_board/xidatong-riscv64/src/Makefile | 4 + .../xidatong-riscv64/src/k210_bringup.c | 9 + .../xidatong-riscv64/src/k210_w5500.c | 470 ++++++++++++ .../xidatong-riscv64/src/k210_w5500.h | 137 ++++ .../aiit_board/xidatong-riscv64/src/w5500.c | 673 ++++++++++++++++++ .../aiit_board/xidatong-riscv64/src/w5500.h | 274 +++++++ .../xidatong-riscv64/src/w5500_demo.c | 30 + .../app_match_nuttx/apps/nshlib/nsh.h | 4 + .../apps/nshlib/nsh_Applicationscmd.c | 13 + .../app_match_nuttx/apps/nshlib/nsh_command.c | 4 + 14 files changed, 1761 insertions(+) rename Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/{ec200nsh => 4gnsh}/defconfig (100%) create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/netnsh/defconfig create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/wifinsh/defconfig create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.c create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.h create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.c create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.h create mode 100755 Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500_demo.c diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig index 149a53caf..1719f8692 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig @@ -144,4 +144,8 @@ menuconfig BSP_USING_ESP8266 bool "Using ESP8266 device" default n +menuconfig BSP_USING_W5500 + bool "Using W5500 device" + default n + endif # ARCH_BOARD_XIDATONG_RISCV64 diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/ec200nsh/defconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/4gnsh/defconfig similarity index 100% rename from Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/ec200nsh/defconfig rename to Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/4gnsh/defconfig diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/netnsh/defconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/netnsh/defconfig new file mode 100755 index 000000000..174100a02 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/netnsh/defconfig @@ -0,0 +1,61 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ADD_NUTTX_FETURES=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="xidatong-riscv64" +CONFIG_ARCH_BOARD_XIDATONG_RISCV64=y +CONFIG_ARCH_CHIP="k210" +CONFIG_ARCH_CHIP_K210=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BINFMT_DISABLE=y +CONFIG_BOARD_LOOPSPERMSEC=46000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=2097152 +CONFIG_RAM_START=0x80400000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_CMD_HISTORY_LEN=100 +CONFIG_READLINE_CMD_HISTORY_LINELEN=120 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=28 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_TESTING_GETPRIME=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_HPWORK=y +CONFIG_DEV_GPIO=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BSP_USING_W5500=y \ No newline at end of file diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/wifinsh/defconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/wifinsh/defconfig new file mode 100755 index 000000000..20095a7a8 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/configs/wifinsh/defconfig @@ -0,0 +1,78 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_STANDARD_SERIAL is not set +CONFIG_ADD_NUTTX_FETURES=y +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="xidatong-riscv64" +CONFIG_ARCH_BOARD_XIDATONG_RISCV64=y +CONFIG_ARCH_CHIP="k210" +CONFIG_ARCH_CHIP_K210=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BINFMT_DISABLE=y +CONFIG_BOARD_LOOPSPERMSEC=46000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_STACKSIZE=3072 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=2097152 +CONFIG_RAM_START=0x80400000 +CONFIG_RAW_BINARY=y +CONFIG_READLINE_CMD_HISTORY=y +CONFIG_READLINE_CMD_HISTORY_LEN=100 +CONFIG_READLINE_CMD_HISTORY_LINELEN=120 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=28 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=20 +CONFIG_TESTING_GETPRIME=y +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_HPWORK=y +CONFIG_DEV_GPIO=y +CONFIG_BOARDCTL_RESET=y +CONFIG_U16550_UART=y +CONFIG_U16550_UART2=y +CONFIG_U16550_UART2_BASE=0x50220000 +CONFIG_U16550_UART2_CLOCK=195000000 +CONFIG_U16550_UART2_IRQ=39 +CONFIG_U16550_UART2_BAUD=115200 +CONFIG_U16550_UART2_PARITY=0 +CONFIG_U16550_UART2_BITS=8 +CONFIG_U16550_UART2_2STOP=0 +CONFIG_U16550_UART2_RXBUFSIZE=256 +CONFIG_U16550_UART2_TXBUFSIZE=256 +CONFIG_U16550_NO_SERIAL_CONSOLE=y +CONFIG_U16550_SUPRESS_INITIAL_CONFIG=y +CONFIG_SERIAL_UART_ARCH_MMIO=y +CONFIG_U16550_REGINCR=4 +CONFIG_U16550_REGWIDTH=32 +CONFIG_U16550_ADDRWIDTH=32 +CONFIG_BSP_USING_ESP8266=y \ No newline at end of file diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile index cfc63483f..2e9e77622 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile @@ -62,4 +62,8 @@ ifeq ($(CONFIG_BSP_USING_ESP8266),y) CSRCS += k210_esp8266.c esp8266_demo.c endif +ifeq ($(CONFIG_BSP_USING_W5500),y) +CSRCS += k210_w5500.c w5500.c w5500_demo.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_bringup.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_bringup.c index 2514b194a..ad58f3a4a 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_bringup.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_bringup.c @@ -57,6 +57,10 @@ # include "k210_esp8266.h" #endif +#ifdef CONFIG_BSP_USING_W5500 +# include "k210_w5500.h" +#endif + #include "k210_sysctl.h" /**************************************************************************** @@ -131,5 +135,10 @@ int k210_bringup(void) board_esp8266_initialize(); #endif +#ifdef CONFIG_BSP_USING_W5500 + k210_sysctl_init(); + board_w5500_initialize(); +#endif + return ret; } diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.c new file mode 100755 index 000000000..6c7363291 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.c @@ -0,0 +1,470 @@ +/* +* Copyright (c) 2022 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file k210_w5500.c +* @brief support to register w5500 pointer and function +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-9-14 +*/ + +#include +#include +#include +#include "ctype.h" +#include "k210_w5500.h" + +#define w_print printf + +/******************************************************************************/ + +struct w5500_dev_s g_w5500dev; +static char *w5500_dev_name = "/dev/w5500"; + +/******************************************************************************/ + +void w5500_print_buf(int size, uint8_t *buf) +{ + char ch[10] = {0}; + char temp[256] = {0}; + + if(size >= 256) + size = 256; + + for(int i = 0; i < size; i++) + { + if(buf[i] == '\r') + { + strcat(temp, "\\r"); + } + else if(buf[i] == '\n') + { + strcat(temp, "\\n"); + } + else if(isascii(buf[i])) + { + snprintf(ch, sizeof(ch), "%c", buf[i]); + strcat(temp, ch); + } + else + { + snprintf(ch, sizeof(ch), "%#x ", buf[i]); + strcat(temp, ch); + } + } + if(size) + w_print("w5500 read %d data: %s\n", size, temp); +} + +//int w5500_read_buf(void *dev, int *size, uint8_t *buf) +//{ +// uart_dev_t *uart_dev = (uart_dev_t *)dev; +// int cur_size = uart_dev->recv.head - uart_dev->recv.tail; +// *size = *size > cur_size ? cur_size : *size; +// memcpy(buf, uart_dev->recv.buffer, *size); +// uart_dev->recv.head = uart_dev->recv.tail; +// w5500_print_buf(*size, buf); +// return *size; +//} + +/**************************************************************************** + * Name: w5500_data_work + * + * Description: + * thread task w5500_data_work + * + ****************************************************************************/ +static FAR void w5500_data_work(FAR void *arg) +{ + struct w5500_dev_s *w5500_dev = (struct w5500_dev_s *)arg; +// uart_dev_t *uart_dev = w5500_dev->uart_dev; + nxsem_wait(&w5500_dev->waitsem); + w5500_dev->recv_size = W5500_RECV_BUF_SIZE; +// w5500_read_buf(uart_dev, &w5500_dev->recv_size, w5500_dev->recv_buf); + work_queue(HPWORK, &w5500_dev->irqwork, w5500_data_work, w5500_dev, W5500_INCREMENT); +// w5500info("uart size %d ok!\n", w5500_dev->recv_size); +} + +static int w5500_bringup(struct w5500_dev_s *dev) +{ +// struct w5500_dev_s *w5500_dev = &g_w5500dev; + + dev->uart_fd = open(dev->dev_name, O_RDWR); + + w5500info("open %s fd = %d\n", dev->dev_name, dev->uart_fd); + + work_queue(HPWORK, &dev->irqwork, w5500_data_work, dev, W5500_INCREMENT); + return OK; +} + +static int w5500_write_config(struct w5500_dev_s *dev) +{ + return OK; +} + +static int w5500_shutdown(struct w5500_dev_s *dev) +{ + close(dev->uart_fd); + return OK; +} + +static int w5500_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + + uint8_t ref_cnt; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct w5500_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Increment the reference count */ + ref_cnt = priv->crefs + 1; + + if(ref_cnt == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + nxsem_post(&priv->devsem); + return -EMFILE; + } + + /* When the reference increments to 1, this is the first open event + * on the driver.. and the time when we must initialize the driver. + */ + + if(ref_cnt == 1) + { + ret = w5500_bringup(priv); + + if(ret < 0) + { + w5500err("ERROR: w5500_bringup failed: %d\n", ret); + nxsem_post(&priv->devsem); + return ret; + } + + ret = w5500_write_config(priv); + + if(ret < 0) + { + w5500err("ERROR: w5500_write_config failed: %d\n", ret); + nxsem_post(&priv->devsem); + return ret; + } + } + + /* Save the new open count on success */ + priv->crefs = ref_cnt; + + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: w5500_close + ****************************************************************************/ + +static int w5500_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct w5500_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Decrement the reference count unless it would decrement a negative + * value. + */ + + if(priv->crefs >= 1) + { + priv->crefs--; + } + + /* When the count decrements to zero, there are no further open references + * to the driver and it w5500 be uninitialized. + */ + + if(priv->crefs == 0) + { + w5500_shutdown(priv); + } + + nxsem_post(&priv->devsem); + return OK; +} + +/**************************************************************************** + * Name: w5500_read + ****************************************************************************/ + +static ssize_t w5500_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + int ret, buf_size = len; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct w5500_dev_s *)inode->i_private; + + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + buf_size = len > priv->recv_size ? priv->recv_size : len; + memcpy(buffer, priv->recv_buf, buf_size); + nxsem_post(&priv->devsem); + return ret; +} + + +/**************************************************************************** + * Name: w5500_write + ****************************************************************************/ + +static ssize_t w5500_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + int ret; + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct w5500_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + ret = write(priv->uart_fd, buffer, len); + w5500info("write fd %d len %ld ret = %d\n", priv->uart_fd, len, ret); + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: w5500_ioctl + ****************************************************************************/ + +static int w5500_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + FAR uint32_t *ptr; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct w5500_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Process the IOCTL by command */ + + switch(cmd) + { + case W5500IOC_SETFREQUENCY: /* arg: Pointer to uint32_t frequency value */ + ptr = (FAR uint32_t *)((uintptr_t)arg); + DEBUGASSERT(priv->config != NULL && ptr != NULL); + break; + + default: + ret = -ENOTTY; + break; + } + + nxsem_post(&priv->devsem); + return ret; +} + +void w5500_notify(uart_dev_t *dev) +{ + nxsem_post(&g_w5500dev.waitsem); +} + +/**************************************************************************** + * Name: w5500_poll + ****************************************************************************/ + +static int w5500_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode; + FAR struct w5500_dev_s *priv; + + int ret; + + w5500info("setup: %d\n", (int)setup); + + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct w5500_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + w5500err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + if(setup) + { + /* Ignore waits that do not include POLLIN */ + if((fds->events & POLLIN) == 0) + { + w5500err("ERROR: Missing POLLIN: revents: %08x\n", fds->revents); + nxsem_post(&priv->devsem); + return -EDEADLK; + } + w5500_notify(priv->uart_dev); + } + else if(fds->priv) + { + /* This is a request to tear down the poll. */ + struct pollfd **slot = (struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + /* Remove all memory of the poll setup */ + *slot = NULL; + fds->priv = NULL; + } + + nxsem_post(&priv->devsem); + return ret; +} + + +static const struct file_operations w5500_fops = +{ + w5500_open, /* open */ + w5500_close, /* close */ + w5500_read, /* read */ + w5500_write, /* write */ + NULL, /* seek */ + w5500_ioctl, /* ioctl */ + w5500_poll /* poll */ +}; + + +/**************************************************************************** + * Name: w5500_register + * + * Description: + * Register /dev/ext_uartN + * + ****************************************************************************/ +static int w5500_register(FAR const char *devpath) +{ + FAR struct w5500_dev_s *priv = &g_w5500dev; + int ret = 0; + + nxsem_init(&priv->devsem, 0, 1); + nxsem_init(&priv->waitsem, 0, 0); + nxsem_set_protocol(&priv->waitsem, SEM_PRIO_NONE); + + /* Register the driver */ + ret = register_driver(devpath, &w5500_fops, 0666, priv); + if(ret < 0) + { + kmm_free(priv); + } + + return ret; +} + +/**************************************************************************** + * Name: w5500_init + * + * Description: + * Ch376 default initialization function + * + ****************************************************************************/ + +void board_w5500_initialize(void) +{ + //simluate SPI bus + k210_fpioa_config(BSP_W5500_SCLK, HS_GPIO(FPIOA_W5500_SCLK) | K210_IOFLAG_GPIOHS); + k210_fpioa_config(BSP_W5500_NRST, HS_GPIO(FPIOA_W5500_NRST) | K210_IOFLAG_GPIOHS); + k210_fpioa_config(BSP_W5500_MOSI, HS_GPIO(FPIOA_W5500_MOSI) | K210_IOFLAG_GPIOHS); + k210_fpioa_config(BSP_W5500_MISO, HS_GPIO(FPIOA_W5500_MISO) | K210_IOFLAG_GPIOHS); + k210_fpioa_config(BSP_W5500_NCS, HS_GPIO(FPIOA_W5500_NCS) | K210_IOFLAG_GPIOHS); + k210_fpioa_config(BSP_W5500_NINT, HS_GPIO(FPIOA_W5500_NINT) | K210_IOFLAG_GPIOHS); + + k210_gpiohs_set_direction(FPIOA_W5500_MISO, GPIO_DM_INPUT); + k210_gpiohs_set_direction(FPIOA_W5500_NRST, GPIO_DM_OUTPUT); + k210_gpiohs_set_direction(FPIOA_W5500_SCLK, GPIO_DM_OUTPUT); + k210_gpiohs_set_direction(FPIOA_W5500_MOSI, GPIO_DM_OUTPUT); + k210_gpiohs_set_direction(FPIOA_W5500_NCS, GPIO_DM_OUTPUT); + k210_gpiohs_set_direction(FPIOA_W5500_NINT, GPIO_DM_INPUT); + + k210_gpiohs_set_value(FPIOA_W5500_SCLK, GPIO_PV_HIGH); + k210_gpiohs_set_value(FPIOA_W5500_MOSI, GPIO_PV_HIGH); + k210_gpiohs_set_value(FPIOA_W5500_NCS, GPIO_PV_LOW); + k210_gpiohs_set_value(FPIOA_W5500_NRST, GPIO_PV_HIGH); + + w5500_register(w5500_dev_name); + w5500info("dev %s ok!\n", w5500_dev_name); +} + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.h b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.h new file mode 100755 index 000000000..27c543bbe --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_w5500.h @@ -0,0 +1,137 @@ +/* +* Copyright (c) 2022 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file k210_w5500.h +* @brief define aiit-riscv64-board w5500 function and struct +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-09-14 +*/ + +#ifndef __K210_W5500_H_ +#define __K210_W5500_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "riscv_internal.h" + +#include "k210_config.h" +#include "k210_fpioa.h" +#include "k210_gpiohs.h" +#include "xidatong-riscv64.h" +#include "nuttx/serial/serial.h" + +/* Define W5500 PIN NUM */ + +#define BSP_W5500_SCLK 9 +#define BSP_W5500_MISO 10 +#define BSP_W5500_MOSI 11 +#define BSP_W5500_NCS 12 +#define BSP_W5500_NRST 13 +#define BSP_W5500_NINT 14 + +/* Define w5500 FPIOA NUMBER */ + +//#define FPIOA_W5500_SCLK 83 +//#define FPIOA_W5500_MISO 70 +//#define FPIOA_W5500_MOSI 71 +//#define FPIOA_W5500_NCS 78 +// +//#define FPIOA_W5500_NRST 4 +//#define FPIOA_W5500_INT 5 + +//#define FPIOA_W5500_NRST 0 +//#define FPIOA_W5500_NINT 9 +//#define FPIOA_W5500_SCLK 28 +//#define FPIOA_W5500_MOSI 29 +//#define FPIOA_W5500_MISO 23 +//#define FPIOA_W5500_NCS 31 + +#define FPIOA_W5500_NRST 0 +#define FPIOA_W5500_NINT 9 +#define FPIOA_W5500_SCLK 28 +#define FPIOA_W5500_MISO 29 +#define FPIOA_W5500_MOSI 23 +#define FPIOA_W5500_NCS 31 + +#define W5500_FUNC_GPIO(n) ((K210_IO_FUNC_GPIOHS0 + n) | K210_IOFLAG_GPIOHS) + +#define W5500IOC_SETFREQUENCY _WLIOC(0x0001) /* arg: Pointer to uint32_t frequency value */ +#define W5500IOC_GETFREQUENCY _WLIOC(0x0002) /* arg: Pointer to uint32_t frequency value */ + +/* w5500 debug */ +#ifdef CONFIG_DEBUG_W5500_ERROR +# define w5500err _err +#else +# define w5500err _none +#endif + +#ifdef CONFIG_DEBUG_W5500_WARN +# define w5500warn _warn +#else +# define w5500warn _none +#endif + +#ifdef CONFIG_DEBUG_W5500_INFO +# define w5500info _info +#else +# define w5500info _none +#endif + +#define W5500_RECV_BUF_SIZE 256 +#define W5500_INCREMENT MSEC2TICK(33) + +struct w5500_config_s +{ + int (*attach)(FAR const struct w5500_config_s *config, xcpt_t isr, + FAR void *arg); + void (*enable)(FAR const struct w5500_config_s *config, bool enable); + void (*clear)(FAR const struct w5500_config_s *config); + + void (*wakeup)(FAR const struct w5500_config_s *config); + void (*nreset)(FAR const struct w5500_config_s *config, bool state); +}; + + +struct w5500_dev_s +{ + uint8_t crefs; /* Number of times the device + * has been opened */ + uint8_t nwaiters; /* Number of threads waiting for + * data */ + sem_t devsem; /* Manages exclusive access to + * this structure */ + sem_t waitsem; /* Used to wait for the + * availability of data */ + FAR const struct w5500_config_s *config; /* Board configuration data */ + struct work_s irqwork; /* Supports the interrupt + * handling "bottom half" */ + char *dev_name; + int uart_fd; + uart_dev_t *uart_dev; + int recv_size; + uint8_t recv_buf[W5500_RECV_BUF_SIZE]; +}; + +void board_w5500_initialize(void); + +#endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.c new file mode 100755 index 000000000..528ec4841 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.c @@ -0,0 +1,673 @@ +/* +* Copyright (c) 2022 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file w5500.c +* @brief w5500 driver based on simulated SPI +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-9-14 +*/ + +#include "nuttx/arch.h" +#include "w5500.h" +#include "k210_w5500.h" +#include "k210_gpio_common.h" + +/*----------------------------------------------------------------------------*/ + +#define w_print printf +#define w_delay() up_udelay(1) + +#define NCS_L() k210_gpiohs_set_value(FPIOA_W5500_NCS, GPIO_PV_LOW); w_delay(); +#define NCS_H() k210_gpiohs_set_value(FPIOA_W5500_NCS, GPIO_PV_HIGH); w_delay(); +#define SCLK_L() k210_gpiohs_set_value(FPIOA_W5500_SCLK, GPIO_PV_LOW); w_delay(); +#define SCLK_H() k210_gpiohs_set_value(FPIOA_W5500_SCLK, GPIO_PV_HIGH); w_delay(); +#define MOSI_L() k210_gpiohs_set_value(FPIOA_W5500_MOSI, GPIO_PV_LOW); w_delay(); +#define MOSI_H() k210_gpiohs_set_value(FPIOA_W5500_MOSI, GPIO_PV_HIGH); w_delay(); + +#define RST_L() k210_gpiohs_set_value(FPIOA_W5500_NRST, GPIO_PV_LOW); up_mdelay(200); +#define RST_H() k210_gpiohs_set_value(FPIOA_W5500_NRST, GPIO_PV_HIGH); up_mdelay(200); + +#define SOCK_WR_REG(_sock) (VDM | RWB_WRITE | (_sock * 0x20 + 0x10)) + +/*----------------------------------------------------------------------------*/ + +/* network parameter definition */ + +w5500_param_t w5500_param; + +#define W5500_BUF_LEN 30 + +char test_str[] = {"ping test!\r\n"}; + +/*----------------------------------------------------------------------------*/ + +static uint8_t spi_read_byte(void) +{ + uint8_t i, dat = 0; + SCLK_L(); + + for(i = 0; i < 8; i++) + { + SCLK_H(); + dat <<= 1; + dat |= k210_gpiohs_get_value(FPIOA_W5500_MISO); + w_delay(); + SCLK_L(); + } + + return dat; +} + +static void spi_write_byte(uint8_t dat) +{ + uint8_t i; + + for(i = 0; i < 8; i++) + { + SCLK_L(); + + if((dat << i) & 0x80) + { + MOSI_H(); + } + else + { + MOSI_L(); + } + + SCLK_H(); + } + + SCLK_L(); +} + +static void spi_write_short(uint16_t dat) +{ + spi_write_byte((uint8_t)(dat / 256)); + spi_write_byte(dat); +} + +static void w5500_write_byte(uint16_t reg, uint8_t dat) +{ + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM1 | RWB_WRITE | COMMON_R); + spi_write_byte(dat); + NCS_H(); +} + +static void w5500_write_short(uint16_t reg, uint16_t dat) +{ + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM2 | RWB_WRITE | COMMON_R); + spi_write_short(dat); + NCS_H(); +} + +static void w5500_write_bytes(uint16_t reg, uint8_t *dat, uint16_t size) +{ + uint16_t i; + NCS_L(); + spi_write_short(reg); + spi_write_byte(VDM | RWB_WRITE | COMMON_R); + + for(i = 0; i < size; i++) + { + spi_write_byte(*dat++); + } + + NCS_H(); +} + +void w5500_write_sock_byte(socket_t sock, uint16_t reg, uint8_t dat) +{ + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM1 | RWB_WRITE | (sock * 0x20 + 0x08)); + spi_write_byte(dat); + NCS_H(); +} + + +void w5500_write_sock_short(socket_t sock, uint16_t reg, uint16_t dat) +{ + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM2 | RWB_WRITE | (sock * 0x20 + 0x08)); + spi_write_short(dat); + NCS_H(); +} + +void w5500_write_sock_long(socket_t sock, uint16_t reg, uint8_t *dat) +{ + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM4 | RWB_WRITE | (sock * 0x20 + 0x08)); + spi_write_byte(*dat++); + spi_write_byte(*dat++); + spi_write_byte(*dat++); + spi_write_byte(*dat++); + NCS_H(); +} + +uint8_t w5500_read_byte(uint16_t reg) +{ + uint8_t val; + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM1 | RWB_READ | COMMON_R); + val = spi_read_byte(); + NCS_H(); + return val; +} + +uint8_t w5500_read_sock_byte(socket_t sock, uint16_t reg) +{ + uint8_t val; + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM1 | RWB_READ | (sock * 0x20 + 0x08)); + val = spi_read_byte(); + NCS_H(); + return val; +} + +uint16_t w5500_read_sock_short(socket_t sock, uint16_t reg) +{ + uint16_t val; + NCS_L(); + spi_write_short(reg); + spi_write_byte(FDM2 | RWB_READ |(sock * 0x20 + 0x08)); + val = spi_read_byte(); + val *= 256; + val |= spi_read_byte(); + NCS_H(); + return val; +} + +uint16_t w5500_read_sock_bytes(socket_t sock, uint8_t *dat) +{ + uint16_t recv_size, write_addr; + uint16_t recv_addr; + uint16_t i; + uint8_t val; + recv_size = w5500_read_sock_short(sock, W5500_SN_RX_RSR_REG); + + //no receive data + if(recv_size == 0) + { + return 0; + } + + if(recv_size > W5500_MAX_PACK_SIZE) + { + recv_size = W5500_MAX_PACK_SIZE; + } + + recv_addr = w5500_read_sock_short(sock, W5500_SN_RX_RD_REG); + write_addr = recv_addr; + + //calculate physical address + recv_addr &= (SOCK_RECV_SIZE - 1); + NCS_L(); + spi_write_short(recv_addr); + spi_write_byte(VDM | RWB_READ | (sock * 0x20 + 0x18)); + + if((recv_addr + recv_size) < SOCK_RECV_SIZE) + { + for(i = 0; i < recv_size; i++) + { + val = spi_read_byte(); + *dat = val; + dat++; + } + } + else + { + recv_addr = SOCK_RECV_SIZE - recv_addr; + + for(i = 0; i < recv_addr; i++) + { + val = spi_read_byte(); + *dat = val; + dat++; + } + + NCS_H(); + NCS_L(); + spi_write_short(0x00); + spi_write_byte(VDM | RWB_READ | (sock * 0x20 + 0x18)); + + for(; i < recv_size; i++) + { + val= spi_read_byte(); + *dat = val; + dat++; + } + } + + NCS_H(); + write_addr += recv_size; + + w5500_write_sock_short(sock, W5500_SN_RX_RD_REG, write_addr); + //start receive + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_RECV); + return recv_size; +} + +void w5500_write_sock_bytes(socket_t sock, uint8_t *dat, uint16_t size) +{ + uint16_t recv_addr, write_addr; + uint16_t i; + + // if udp mode, set ip and port + if(w5500_read_sock_byte(sock, W5500_SN_MR_REG) != SOCK_UDP) + { + w5500_write_sock_long(sock, W5500_SN_DIPR_REG, w5500_param.udp_ip); + w5500_write_sock_short(sock, W5500_SN_DPORTR_REG, w5500_param.udp_port); + } + + recv_addr = w5500_read_sock_short(sock, W5500_SN_TX_WR_REG); + write_addr = recv_addr; + recv_addr &= (SOCK_SEND_SIZE - 1); + + NCS_L(); + spi_write_short(recv_addr); + spi_write_byte(VDM | RWB_WRITE | (sock * 0x20 + 0x10)); + + if((recv_addr + size) < SOCK_SEND_SIZE) + { + for(i = 0; i < size; i++) + { + spi_write_byte(*dat++); + } + } + else + { + recv_addr = SOCK_SEND_SIZE - recv_addr; + + for(i = 0; i < recv_addr; i++) + { + spi_write_byte(*dat++); + } + + NCS_H(); + NCS_L(); + + spi_write_short(0x00); + spi_write_byte(VDM | RWB_WRITE | (sock * 0x20 + 0x10)); + + for(; i < size; i++) + { + spi_write_byte(*dat++); + } + } + + NCS_H(); + write_addr += size; + + w5500_write_sock_short(sock, W5500_SN_TX_WR_REG, write_addr); + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_SEND); +} + +/*w5500 reset pin keep 500us low at least*/ +void w5500_reset(void) +{ + uint8_t dat = 0; + + RST_L(); + RST_H(); + + //wait connect ok + while((dat & LINK) == 0) + { + up_mdelay(500); + dat = w5500_read_byte(W5500_PHYCFGR_REG); + w_print(" PHYCFG = %x\n", dat); + } +} + +void w5500_config_init(void) +{ + uint8_t i = 0; + + //software reset, set 1 and auto clear 0 + w5500_write_byte(W5500_MR_REG, MR_RST); + up_mdelay(100); + + w5500_write_bytes(W5500_GAR_REG, w5500_param.gw_addr, 4); + w5500_write_bytes(W5500_SUBR_REG, w5500_param.ip_mask, 4); + w5500_write_bytes(W5500_SHAR_REG, w5500_param.mac_addr, 6); + w5500_write_bytes(W5500_SIPR_REG, w5500_param.ip_addr, 4); + + //set socket rx and tx memory size 2k + for(i = 0; i < 8; i++) + { + w5500_write_sock_byte(i, W5500_SN_RXBUF_SIZE_REG, 0x02); + w5500_write_sock_byte(i, W5500_SN_TXBUF_SIZE_REG, 0x02); + } + + //set retry time 200ms (0x07d0 = 2000) + w5500_write_short(W5500_RTR_REG, 0x07d0); + + //retry time with 8, when exceed it, produce overtime interrupt, set W5500_SN_IR_REG(TIMEOUT) + w5500_write_byte(W5500_RCR_REG, 8); +} + +uint8_t w5500_detect_gateway(void) +{ + uint8_t ip_addr[4] = {w5500_param.ip_addr[0] + 1, w5500_param.ip_addr[1] + 1, w5500_param.ip_addr[2] + 1, w5500_param.ip_addr[3] + 1}; + + //check gateway and get gateway phyiscal address + w5500_write_sock_long(0, W5500_SN_DIPR_REG, ip_addr); + w5500_write_sock_byte(0, W5500_SN_MR_REG, SN_MR_TCP); + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_OPEN); + up_mdelay(5); + + if(w5500_read_sock_byte(0, W5500_SN_SR_REG) != SOCK_INIT) + { + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE); + return FALSE; + } + + //set socket connection mode + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CONNECT); + + do + { + uint8_t val = 0; + //read socket0 interrupt register + val = w5500_read_sock_byte(0, W5500_SN_IR_REG); + + if(val != 0) + { + w5500_write_sock_byte(0, W5500_SN_IR_REG, val); + } + + up_mdelay(5); + + if((val & IR_TIMEOUT) == IR_TIMEOUT) + { + return FALSE; + } + else if(w5500_read_sock_byte(0, W5500_SN_DHAR_REG) != 0xff) + { + //close socket + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE); + return TRUE; + } + } while(1); + return TRUE; +} + +// socket port (0 - 7) initialization +void w5500_socket_init(socket_t sock) +{ + //max partition bytes = 30 + w5500_write_sock_short(0, W5500_SN_MSSR_REG, 30); + + switch(sock) + { + case 0: + w5500_write_sock_short(0, W5500_SN_PORT_REG, w5500_param.sock.local_port); + w5500_write_sock_short(0, W5500_SN_DPORTR_REG, w5500_param.sock.dst_port); + w5500_write_sock_long(0, W5500_SN_DIPR_REG, w5500_param.sock.dst_ip); + break; + + default: + break; + } +} + +uint8_t w5500_socket_connect(socket_t sock) +{ + w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_TCP); + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN); + up_mdelay(5); + + if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_INIT) + { + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE); + return FALSE; + } + + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CONNECT); + return TRUE; +} + +uint8_t w5500_socket_listen(socket_t sock) +{ + w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_TCP); + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN); + up_mdelay(5); + + if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_INIT) + { + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE); + return FALSE; + } + + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_LISTEN); + up_mdelay(5); + + if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_LISTEN) + { + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE); + return FALSE; + } + + return TRUE; +} + +uint8_t w5500_socket_set_udp(socket_t sock) +{ + w5500_write_sock_byte(sock, W5500_SN_MR_REG, SN_MR_UDP); + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_OPEN); + up_mdelay(5); + + if(w5500_read_sock_byte(sock, W5500_SN_SR_REG) != SOCK_UDP) + { + w5500_write_sock_byte(sock, W5500_SN_CR_REG, SN_CR_CLOSE); + return FALSE; + } + return TRUE; +} + +void w5500_irq_process(void) +{ + uint8_t ir_flag, sn_flag; + ir_flag = w5500_read_byte(W5500_SIR_REG); + do + { + w_print("SIR = %x\n", ir_flag); + + //handle socket0 event + if((ir_flag & S0_INT) == S0_INT) + { + sn_flag = w5500_read_sock_byte(0, W5500_SN_IR_REG); + w5500_write_sock_byte(0, W5500_SN_IR_REG, sn_flag); + + if(sn_flag & IR_CON) + { + //socket connection finished + w5500_param.sock.flag |= SOCK_FLAG_CONN; + } + + if(sn_flag & IR_DISCON) + { + //disconnect state + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE); + w5500_socket_init(0); + w5500_param.sock.flag = 0; + } + + if(sn_flag & IR_SEND_OK) + { + //send one package ok + w5500_param.sock.state |= SOCK_STAT_SEND; + } + + if(sn_flag & IR_RECV) + { + w5500_param.sock.state |= SOCK_STAT_RECV; + } + + if(sn_flag & IR_TIMEOUT) + { + //close socket, connection failed + w5500_write_sock_byte(0, W5500_SN_CR_REG, SN_CR_CLOSE); + w5500_param.sock.flag = 0; + } + } + ir_flag = w5500_read_byte(W5500_SIR_REG); + }while(ir_flag); + + w_print("Flag = %x State = %x\n", w5500_param.sock.flag, w5500_param.sock.state) ; +} + +void w5500_intialization(void) +{ + w5500_config_init(); + w5500_detect_gateway(); + w5500_socket_init(0); +} + +char test_mac_addr[] = {0x0C, 0x29, 0xAB, 0x7C, 0x00, 0x01}; + +//char test_ip_addr[] = {192, 168, 250, 189}; +//char test_ip_mask[] = {255, 255, 255, 0}; +//char test_gw_addr[] = {192, 168, 250, 1}; +//char test_dst_ip[] = {192, 168, 250, 1}; + +char test_ip_addr[] = {10, 0, 30, 50}; +char test_ip_mask[] = {255, 255, 255, 0}; +char test_gw_addr[] = {10, 0, 30, 1}; +char test_dst_ip[] = {10, 0, 30, 57}; + +void w5500_load_param(void) +{ + w5500_param_t *param = &w5500_param; + memcpy(param->ip_addr, test_ip_addr, sizeof(test_ip_addr)); + memcpy(param->ip_mask, test_ip_mask, sizeof(test_ip_mask)); + memcpy(param->gw_addr, test_gw_addr, sizeof(test_gw_addr)); + memcpy(param->mac_addr, test_mac_addr, sizeof(test_mac_addr)); + memcpy(param->sock.dst_ip, test_dst_ip, sizeof(test_dst_ip)); + param->sock.local_port = 5000; + param->sock.dst_port = 6000; + param->sock.mode = SOCK_TCP_CLI; +} + +void w5500_socket_config(void) +{ + if(w5500_param.sock.flag == 0) + { + if(w5500_param.sock.mode == SOCK_TCP_SVR) + { + if(w5500_socket_listen(0) == TRUE) + { + w5500_param.sock.flag = SOCK_FLAG_INIT; + } + else + { + w5500_param.sock.flag = 0; + } + } + else if(w5500_param.sock.mode == SOCK_TCP_CLI) + { + if(w5500_socket_connect(0) == TRUE) + { + w5500_param.sock.flag = SOCK_FLAG_INIT; + } + else + { + w5500_param.sock.flag = 0; + } + + w_print("TCP state = %d\n", w5500_param.sock.flag); + } + else + { + if(w5500_socket_set_udp(0) == TRUE) + { + w5500_param.sock.flag = SOCK_FLAG_INIT|SOCK_FLAG_CONN; + } + else + { + w5500_param.sock.flag = 0; + } + } + } +} + +void w5500_socket_process(socket_t sock) +{ + uint16_t size; + + static uint8_t rx_buf[W5500_BUF_LEN] = {0}; + static uint8_t tx_buf[W5500_BUF_LEN] = {0}; + + size = w5500_read_sock_bytes(sock, rx_buf); + memcpy(tx_buf, rx_buf, size); + w5500_write_sock_bytes(sock, tx_buf, size); + + w_print("w5500: "); + for(int i = 0; i < W5500_BUF_LEN; i++) + { + w_print("%x ", rx_buf[i]); + } + w_print("\n"); +} + +int w5500_net_test(void) +{ + uint32_t cnt = 0; + uint8_t tx_buf[W5500_BUF_LEN] = {0}; + + w5500_load_param(); + w5500_reset(); + w5500_intialization(); + w_print("w5500_intialization()\n"); + + while(1) + { + w5500_socket_config(); + w5500_irq_process(); + + if((w5500_param.sock.state & SOCK_STAT_RECV) == SOCK_STAT_RECV) + { + w5500_param.sock.state &= ~SOCK_STAT_RECV; + //receive and send data + w5500_socket_process(0); + } + else if(cnt >= 10) + { + w_print("write flag = %x state = %x\n", w5500_param.sock.flag, w5500_param.sock.state); + if(w5500_param.sock.flag == (SOCK_FLAG_INIT|SOCK_FLAG_CONN)) + { + w5500_param.sock.state &= ~SOCK_STAT_SEND; + memcpy(tx_buf, test_str, strlen(test_str)); + w5500_write_sock_bytes(0, tx_buf, strlen(test_str)); + w_print("write %s ok!\n", test_str); + break; + } + cnt = 0; + } + up_mdelay(1000); + cnt++; + } + + return 1; +} + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.h b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.h new file mode 100755 index 000000000..ee793f961 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500.h @@ -0,0 +1,274 @@ +/* +* Copyright (c) 2022 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** +* @file w5500.h +* @brief w5500 driver +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-9-15 +*/ + +#ifndef _W5500_H_ +#define _W5500_H_ + +/***************** Common Register *****************/ +#define W5500_MR_REG 0x0000 +#define MR_RST 0x80 +#define MR_WOL 0x20 +#define MR_PB 0x10 +#define MR_PPP 0x08 +#define MR_FARP 0x02 + +#define W5500_GAR_REG 0x0001 +#define W5500_SUBR_REG 0x0005 +#define W5500_SHAR_REG 0x0009 +#define W5500_SIPR_REG 0x000f + +#define W5500_INT_REG 0x0013 + +#define W5500_IR_REG 0x0015 +#define IR_CONFLICT 0x80 +#define IR_UNREACH 0x40 +#define IR_PPPOE 0x20 +#define IR_MP 0x10 + +#define W5500_IMR_REG 0x0016 +#define IMR_IR7 0x80 +#define IMR_IR6 0x40 +#define IMR_IR5 0x20 +#define IMR_IR4 0x10 + +#define W5500_SIR_REG 0x0017 +#define S7_INT 0x80 +#define S6_INT 0x40 +#define S5_INT 0x20 +#define S4_INT 0x10 +#define S3_INT 0x08 +#define S2_INT 0x04 +#define S1_INT 0x02 +#define S0_INT 0x01 + +#define W5500_SIMR_REG 0x0018 +#define S7_IMR 0x80 +#define S6_IMR 0x40 +#define S5_IMR 0x20 +#define S4_IMR 0x10 +#define S3_IMR 0x08 +#define S2_IMR 0x04 +#define S1_IMR 0x02 +#define S0_IMR 0x01 + +#define W5500_RTR_REG 0x0019 +#define W5500_RCR_REG 0x001B + +#define W5500_PTIMER_REG 0x001C +#define W5500_PMAGIC_REG 0x001D +#define W5500_PHA_REG 0x001E +#define W5500_PSID_REG 0x0024 +#define W5500_PMRU_REG 0x0026 + +#define W5500_UIPR_REG 0x0028 +#define W5500_UPORT_REG 0x002C + +#define W5500_PHYCFGR_REG 0x002E +#define RST_PHY 0x80 +#define OPMODE 0x40 +#define DPX 0x04 +#define SPD 0x02 +#define LINK 0x01 + +#define W5500_VER_REG 0x0039 + +/********************* Socket Register *******************/ +#define W5500_SN_MR_REG 0x0000 +#define SN_MR_MULTI_MFEN 0x80 +#define SN_MR_BCASTB 0x40 +#define SN_MR_ND_MC_MMB 0x20 +#define SN_MR_UCASTB_MIP6B 0x10 +#define SN_MR_CLOSE 0x00 +#define SN_MR_TCP 0x01 +#define SN_MR_UDP 0x02 +#define SN_MR_MACRAW 0x04 + +#define W5500_SN_CR_REG 0x0001 +#define SN_CR_OPEN 0x01 +#define SN_CR_LISTEN 0x02 +#define SN_CR_CONNECT 0x04 +#define SN_CR_DISCON 0x08 +#define SN_CR_CLOSE 0x10 +#define SN_CR_SEND 0x20 +#define SN_CR_SEND_MAC 0x21 +#define SN_CR_SEND_KEEP 0x22 +#define SN_CR_RECV 0x40 + +#define W5500_SN_IR_REG 0x0002 +#define IR_SEND_OK 0x10 +#define IR_TIMEOUT 0x08 +#define IR_RECV 0x04 +#define IR_DISCON 0x02 +#define IR_CON 0x01 + +#define W5500_SN_SR_REG 0x0003 +#define SOCK_CLOSED 0x00 +#define SOCK_INIT 0x13 +#define SOCK_LISTEN 0x14 +#define SOCK_ESTABLISHED 0x17 +#define SOCK_CLOSE_WAIT 0x1C +#define SOCK_UDP 0x22 +#define SOCK_MACRAW 0x02 + +#define SOCK_SYNSEND 0x15 +#define SOCK_SYNRECV 0x16 +#define SOCK_FIN_WAI 0x18 +#define SOCK_CLOSING 0x1A +#define SOCK_TIME_WAIT 0x1B +#define SOCK_LAST_ACK 0x1D + +#define W5500_SN_PORT_REG 0x0004 +#define W5500_SN_DHAR_REG 0x0006 +#define W5500_SN_DIPR_REG 0x000C +#define W5500_SN_DPORTR_REG 0x0010 + +#define W5500_SN_MSSR_REG 0x0012 +#define W5500_SN_TOS_REG 0x0015 +#define W5500_SN_TTL_REG 0x0016 + +#define W5500_SN_RXBUF_SIZE_REG 0x001E +#define W5500_SN_TXBUF_SIZE_REG 0x001F +#define W5500_SN_TX_FSR_REG 0x0020 +#define W5500_SN_TX_RD_REG 0x0022 +#define W5500_SN_TX_WR_REG 0x0024 +#define W5500_SN_RX_RSR_REG 0x0026 +#define W5500_SN_RX_RD_REG 0x0028 +#define W5500_SN_RX_WR_REG 0x002A + +#define W5500_SN_IMR_REG 0x002C +#define IMR_SENDOK 0x10 +#define IMR_TIMEOUT 0x08 +#define IMR_RECV 0x04 +#define IMR_DISCON 0x02 +#define IMR_CON 0x01 + +#define W5500_SN_FRAG_REG 0x002D +#define W5500_SN_KPALVTR_REG 0x002F + +/************************ SPI Control Data *************************/ + +/* Operation mode bits */ + +#define VDM 0x00 +#define FDM1 0x01 +#define FDM2 0x02 +#define FDM4 0x03 + +/* Read_Write control bit */ +#define RWB_READ 0x00 +#define RWB_WRITE 0x04 + +/* Block select bits */ +#define COMMON_R 0x00 + +/* Socket 0 */ +#define S0_REG 0x08 +#define S0_TX_BUF 0x10 +#define S0_RX_BUF 0x18 + +/* Socket 1 */ +#define S1_REG 0x28 +#define S1_TX_BUF 0x30 +#define S1_RX_BUF 0x38 + +/* Socket 2 */ +#define S2_REG 0x48 +#define S2_TX_BUF 0x50 +#define S2_RX_BUF 0x58 + +/* Socket 3 */ +#define S3_REG 0x68 +#define S3_TX_BUF 0x70 +#define S3_RX_BUF 0x78 + +/* Socket 4 */ +#define S4_REG 0x88 +#define S4_TX_BUF 0x90 +#define S4_RX_BUF 0x98 + +/* Socket 5 */ +#define S5_REG 0xa8 +#define S5_TX_BUF 0xb0 +#define S5_RX_BUF 0xb8 + +/* Socket 6 */ +#define S6_REG 0xc8 +#define S6_TX_BUF 0xd0 +#define S6_RX_BUF 0xd8 + +/* Socket 7 */ +#define S7_REG 0xe8 +#define S7_TX_BUF 0xf0 +#define S7_RX_BUF 0xf8 + +// socket receive buffer size based on RMSR +#define SOCK_RECV_SIZE 2048 +// socket send buffer size based on RMSR +#define SOCK_SEND_SIZE 2048 + +#define W5500_IP_ADDR_LEN 4 +#define W5500_IP_MASK_LEN 4 +#define W5500_GW_ADDR_LEN 4 +#define W5500_MAC_ADDR_LEN 6 + +//for every socket + +// socket mode +#define SOCK_TCP_SVR 0 //server mode +#define SOCK_TCP_CLI 1 //client mode +#define SOCK_UDP_MOD 2 //udp mode + +// socket flag +#define SOCK_FLAG_INIT 1 +#define SOCK_FLAG_CONN 2 + +// socket data state +#define SOCK_STAT_RECV 1 +#define SOCK_STAT_SEND 2 + +typedef struct w5500_socket_s +{ + uint16_t local_port; + uint8_t dst_ip[W5500_IP_ADDR_LEN]; + uint16_t dst_port; + uint8_t mode; // 0: TCP Server; 1: TCP client; 2: UDP + uint8_t flag; // 1: init ok; 2: connected + uint8_t state; // 1: receive one; 2: send ok +}w5500_socket_t; + +typedef struct +{ + uint8_t ip_addr[W5500_IP_ADDR_LEN]; + uint8_t ip_mask[W5500_IP_MASK_LEN]; + uint8_t gw_addr[W5500_GW_ADDR_LEN]; + uint8_t mac_addr[W5500_MAC_ADDR_LEN]; + uint8_t udp_ip[4]; + uint16_t udp_port; + w5500_socket_t sock; +}w5500_param_t; + + +#define W5500_MAX_PACK_SIZE 1460 + +typedef unsigned char socket_t; + +int w5500_net_test(void); + +#endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500_demo.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500_demo.c new file mode 100755 index 000000000..c63ff032d --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/w5500_demo.c @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2022 AIIT XUOS Lab +* XiUOS is licensed under Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* http://license.coscl.org.cn/MulanPSL2 +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +/** + * @file w5500_demo.c + * @brief xidatong-riscv64 w5500_demo.c + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.08.22 + */ + +#include "k210_w5500.h" +#include "w5500.h" + +#define w_print printf + +void W5500Demo(void) +{ + w_print("start %s\n", __func__); + w5500_net_test(); +} diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh.h b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh.h index fade188ab..ec644d2d7 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh.h +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh.h @@ -1470,6 +1470,10 @@ int nsh_foreach_var(FAR struct nsh_vtbl_s *vtbl, nsh_foreach_var_t cb, int cmd_Esp8266(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif +#if defined(CONFIG_BSP_USING_W5500) && !defined(CONFIG_NSH_DISABLE_W5500) + int cmd_W5500(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); +#endif + #if defined(CONFIG_K210_LCD) && !defined(CONFIG_NSH_DISABLE_LCD) int cmd_Lcd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv); #endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_Applicationscmd.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_Applicationscmd.c index d076f1a1a..68a9699ea 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_Applicationscmd.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_Applicationscmd.c @@ -103,6 +103,19 @@ int cmd_Esp8266(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) } #endif +/**************************************************************************** + * Name: cmd_W5500 + ****************************************************************************/ +#if defined(CONFIG_BSP_USING_W5500) && !defined(CONFIG_NSH_DISABLE_W5500) +extern void W5500Demo(void); +int cmd_W5500(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) +{ + nsh_output(vtbl, "Hello, W5500!\n"); + W5500Demo(); + return OK; +} +#endif + /**************************************************************************** * Name: cmd_lcd ****************************************************************************/ diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_command.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_command.c index 260c3ea62..0a7b44d62 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_command.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/apps/nshlib/nsh_command.c @@ -616,6 +616,10 @@ static const struct cmdmap_s g_cmdmap[] = { "esp8266", cmd_Esp8266, 1, 1, "[can demo cmd.]" }, #endif +#if defined(CONFIG_BSP_USING_W5500) && !defined(CONFIG_NSH_DISABLE_W5500) + { "w5500", cmd_W5500, 1, 1, "[can demo cmd.]" }, +#endif + #if defined(CONFIG_K210_LCD) && !defined(CONFIG_NSH_DISABLE_LCD) { "lcd", cmd_Lcd, 1, 1, "[LCD demo cmd.]" }, #endif