diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig index 8b4ca4204..149a53caf 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/Kconfig @@ -140,7 +140,7 @@ menuconfig BSP_USING_CAN default n menuconfig BSP_USING_ESP8266 - depends on U16550_UART3 + depends on U16550_UART2 bool "Using ESP8266 device" default n 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 11551cefc..cfc63483f 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/Makefile @@ -58,4 +58,8 @@ ifeq ($(CONFIG_BSP_USING_CAN),y) CSRCS += k210_can.c can_demo.c endif +ifeq ($(CONFIG_BSP_USING_ESP8266),y) +CSRCS += k210_esp8266.c esp8266_demo.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/esp8266_demo.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/esp8266_demo.c new file mode 100755 index 000000000..c9847894a --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/esp8266_demo.c @@ -0,0 +1,118 @@ +/* +* 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 esp8266_demo.c + * @brief xidatong-riscv64 esp8266_demo.c + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2022.08.22 + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ +#include "k210_esp8266.h" +#include +#include "time.h" + +#define ec_print printf +#define ESP8266_DEMO_TIMEOUT 10 + + +// first: receive \n\rRDY\n\r +// second: AT -> OK + +static int esp8266_read_with_time(int fd, char *buffer, int seconds) +{ + int read_size = 0; + time_t cur_time = time(NULL); + time_t last_time = cur_time; + + while(cur_time < last_time + seconds) + { + read_size = read(fd, buffer, 256); + + if(read_size < 0) + { + ec_print("esp8266 read failed %d\n", read_size); + return -ETIME; + } + else if(read_size) + { + ec_print("esp8266 read size %d ok!\n", read_size); + break; + } + cur_time = time(NULL); + } + return read_size; +} + +int esp8266_check_demo(int fd, char *send_str, char *recv_str) +{ + int ret; + char buf[ESP8266_RECV_BUF_SIZE] = {0}; + + if(send_str) + { + ret = write(fd, send_str, strlen(send_str)); + + if(ret < 0) + { + ec_print("esp8266 write failed %d\n", ret); + return ret; + } + + ec_print("write %s ret = %d\n", send_str, ret); + } + + ret = esp8266_read_with_time(fd, buf, ESP8266_DEMO_TIMEOUT); + if(ret < 0) + { + ec_print("esp8266 read failed %d\n", ret); + return ret; + } + + ec_print("esp8266 read: %s!\n", buf); + + if(strstr(buf, recv_str)) + { + ec_print("esp8266 %s found!\n", recv_str); + } + + return ret; +} + + +void Esp8266Demo(void) +{ + int fd; + + k210_gpiohs_set_value(FPIOA_ESP8266_EN, GPIO_PV_HIGH); + up_mdelay(100); + + ec_print("start %s\n", __func__); + + fd = open("/dev/esp8266", O_RDWR); + if(fd < 0) + { + ec_print("esp8266 open failed %d\n", fd); + return; + } + + up_mdelay(2000); + esp8266_check_demo(fd, "AT\r\n", "OK"); + + close(fd); + + ec_print("end %s\n", __func__); +} diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.c b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.c new file mode 100755 index 000000000..d9ff7b5c8 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.c @@ -0,0 +1,462 @@ +/* +* 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_esp8266.c +* @brief support to register esp8266 pointer and function +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-07-20 +*/ + +#include +#include +#include +#include "ctype.h" +#include "k210_esp8266.h" + +#define ec_print printf + +/******************************************************************************/ + +struct esp8266_dev_s g_esp8266dev; +static char *esp8266_dev_name = "/dev/esp8266"; + +/******************************************************************************/ + +void esp8266_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) + ec_print("esp8266 read %d data: %s\n", size, temp); +} + +int esp8266_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; + esp8266_print_buf(*size, buf); + return *size; +} + +/**************************************************************************** + * Name: esp8266_data_work + * + * Description: + * thread task esp8266_data_work + * + ****************************************************************************/ +static FAR void esp8266_data_work(FAR void *arg) +{ + struct esp8266_dev_s *esp8266_dev = (struct esp8266_dev_s *)arg; + uart_dev_t *uart_dev = esp8266_dev->uart_dev; + nxsem_wait(&esp8266_dev->waitsem); + esp8266_dev->recv_size = ESP8266_RECV_BUF_SIZE; + esp8266_read_buf(uart_dev, &esp8266_dev->recv_size, esp8266_dev->recv_buf); + work_queue(HPWORK, &esp8266_dev->irqwork, esp8266_data_work, esp8266_dev, ESP8266_INCREMENT); +// esp8266info("uart size %d ok!\n", esp8266_dev->recv_size); +} + +static int esp8266_bringup(struct esp8266_dev_s *dev) +{ +// struct esp8266_dev_s *esp8266_dev = &g_esp8266dev; + + dev->uart_fd = open(dev->dev_name, O_RDWR); + + esp8266info("open %s fd = %d\n", dev->dev_name, dev->uart_fd); + + work_queue(HPWORK, &dev->irqwork, esp8266_data_work, dev, ESP8266_INCREMENT); + return OK; +} + +static int esp8266_write_config(struct esp8266_dev_s *dev) +{ + return OK; +} + +static int esp8266_shutdown(struct esp8266_dev_s *dev) +{ + close(dev->uart_fd); + return OK; +} + +static int esp8266_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + + uint8_t ref_cnt; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("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 = esp8266_bringup(priv); + + if(ret < 0) + { + esp8266err("ERROR: esp8266_bringup failed: %d\n", ret); + nxsem_post(&priv->devsem); + return ret; + } + + ret = esp8266_write_config(priv); + + if(ret < 0) + { + esp8266err("ERROR: esp8266_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: esp8266_close + ****************************************************************************/ + +static int esp8266_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("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 esp8266 be uninitialized. + */ + + if(priv->crefs == 0) + { + esp8266_shutdown(priv); + } + + nxsem_post(&priv->devsem); + return OK; +} + +/**************************************************************************** + * Name: esp8266_read + ****************************************************************************/ + +static ssize_t esp8266_read(FAR struct file *filep, FAR char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + int ret, buf_size = len; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("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: esp8266_write + ****************************************************************************/ + +static ssize_t esp8266_write(FAR struct file *filep, FAR const char *buffer, size_t len) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + int ret; + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + ret = write(priv->uart_fd, buffer, len); + esp8266info("write fd %d len %ld ret = %d\n", priv->uart_fd, len, ret); + nxsem_post(&priv->devsem); + return ret; +} + +/**************************************************************************** + * Name: esp8266_ioctl + ****************************************************************************/ + +static int esp8266_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + FAR uint32_t *ptr; + + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + /* Get exclusive access to the driver data structure */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + /* Process the IOCTL by command */ + + switch(cmd) + { + case ESP8266IOC_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; +} + +/**************************************************************************** + * Name: esp8266_poll + ****************************************************************************/ + +static int esp8266_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) +{ + FAR struct inode *inode; + FAR struct esp8266_dev_s *priv; + + int ret; + + esp8266info("setup: %d\n", (int)setup); + + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + DEBUGASSERT(inode && inode->i_private); + + priv = (FAR struct esp8266_dev_s *)inode->i_private; + + /* Are we setting up the poll? Or tearing it down? */ + ret = nxsem_wait(&priv->devsem); + + if(ret < 0) + { + esp8266err("ERROR: nxsem_wait failed: %d\n", ret); + return ret; + } + + if(setup) + { + /* Ignore waits that do not include POLLIN */ + if((fds->events & POLLIN) == 0) + { + esp8266err("ERROR: Missing POLLIN: revents: %08x\n", fds->revents); + nxsem_post(&priv->devsem); + return -EDEADLK; + } + esp8266_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 esp8266_fops = +{ + esp8266_open, /* open */ + esp8266_close, /* close */ + esp8266_read, /* read */ + esp8266_write, /* write */ + NULL, /* seek */ + esp8266_ioctl, /* ioctl */ + esp8266_poll /* poll */ +}; + + +/**************************************************************************** + * Name: esp8266_register + * + * Description: + * Register /dev/ext_uartN + * + ****************************************************************************/ +static int esp8266_register(FAR const char *devpath) +{ + FAR struct esp8266_dev_s *priv = &g_esp8266dev; + 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, &esp8266_fops, 0666, priv); + if(ret < 0) + { + kmm_free(priv); + } + + return ret; +} + +void esp8266_notify(uart_dev_t *dev) +{ + if(dev == g_esp8266dev.uart_dev) + nxsem_post(&g_esp8266dev.waitsem); +} + +/**************************************************************************** + * Name: esp8266_init + * + * Description: + * Ch376 default initialization function + * + ****************************************************************************/ + +void board_esp8266_initialize(void) +{ + k210_fpioa_config(ESP8266_EN_PIN, ESP8266_FUNC_GPIO(FPIOA_ESP8266_EN)); + k210_gpiohs_set_direction(FPIOA_ESP8266_EN, GPIO_DM_OUTPUT); + k210_gpiohs_set_value(FPIOA_ESP8266_EN, GPIO_PV_HIGH); + + fpioa_set_function(ESP8266_RX_PIN, FPIOA_ESP8266_RX); + fpioa_set_function(ESP8266_TX_PIN, FPIOA_ESP8266_TX); + +#if defined(CONFIG_U16550_UART2) + g_esp8266dev.dev_name = "/dev/uart2"; + u16550_register(&g_esp8266dev.uart_dev, 2); + esp8266_register(esp8266_dev_name); + esp8266info("dev %p ok!\n", g_esp8266dev.uart_dev); +#endif +} + diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.h b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.h new file mode 100755 index 000000000..efaa734f4 --- /dev/null +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/aiit_board/xidatong-riscv64/src/k210_esp8266.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_esp8266.h +* @brief define aiit-riscv64-board esp8266 function and struct +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-09-7 +*/ + +#ifndef __K210_ESP8266_H_ +#define __K210_ESP8266_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#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" +#include "nuttx/serial/uart_16550.h" + + +/* Define CH438 PIN NUM */ +#define ESP8266_RX_PIN 6 +#define ESP8266_TX_PIN 7 +#define ESP8266_EN_PIN 8 + +/* Define ch438 FPIOA NUMBER */ +#define FPIOA_ESP8266_RX 66 +#define FPIOA_ESP8266_TX 67 +#define FPIOA_ESP8266_EN 4 + +#define ESP8266_FUNC_GPIO(n) ((K210_IO_FUNC_GPIOHS0 + n) | K210_IOFLAG_GPIOHS) + +#define ESP8266IOC_SETFREQUENCY _WLIOC(0x0001) /* arg: Pointer to uint32_t frequency value */ +#define ESP8266IOC_GETFREQUENCY _WLIOC(0x0002) /* arg: Pointer to uint32_t frequency value */ + +/* esp8266 debug */ +#ifdef CONFIG_DEBUG_ESP8266_ERROR +# define esp8266err _err +#else +# define esp8266err _none +#endif + +#ifdef CONFIG_DEBUG_ESP8266_WARN +# define esp8266warn _warn +#else +# define esp8266warn _none +#endif + +#ifdef CONFIG_DEBUG_ESP8266_INFO +# define esp8266info _info +#else +# define esp8266info _none +#endif + +#define ESP8266_RECV_BUF_SIZE 256 +#define ESP8266_INCREMENT MSEC2TICK(33) + +struct esp8266_config_s +{ + int (*attach)(FAR const struct esp8266_config_s *config, xcpt_t isr, + FAR void *arg); + void (*enable)(FAR const struct esp8266_config_s *config, bool enable); + void (*clear)(FAR const struct esp8266_config_s *config); + + void (*wakeup)(FAR const struct esp8266_config_s *config); + void (*nreset)(FAR const struct esp8266_config_s *config, bool state); +}; + + +struct esp8266_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 esp8266_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[ESP8266_RECV_BUF_SIZE]; +}; + + +void esp8266_notify(uart_dev_t *dev); +void board_esp8266_initialize(void); + +#endif diff --git a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/risc-v/src/k210/k210_fpioa.c b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/risc-v/src/k210/k210_fpioa.c index ad161b9dd..0adcee8db 100644 --- a/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/risc-v/src/k210/k210_fpioa.c +++ b/Ubiquitous/Nuttx_Fusion_XiUOS/app_match_nuttx/nuttx/arch/risc-v/src/k210/k210_fpioa.c @@ -47,11 +47,11 @@ int k210_fpioa_get_io_by_function(uint8_t function) { int index = 0; uint32_t RegValue = 0x0000; - uint32_t *fpioa = (uint32_t *)K210_FPIOA_BASE; + uint32_t *fpioa_base = (uint32_t *)K210_FPIOA_BASE; for (index = 0; index < K210_IO_NUMBER; index++) { - RegValue = getreg32(&fpioa[index]); + RegValue = getreg32(&fpioa_base[index]); if ((RegValue & 0xFF) == function) return index; } @@ -61,7 +61,7 @@ int k210_fpioa_get_io_by_function(uint8_t function) void k210_fpioa_config(uint32_t io, uint32_t ioflags) { - uint32_t *fpioa = (uint32_t *)K210_FPIOA_BASE; + uint32_t *fpioa_base = (uint32_t *)K210_FPIOA_BASE; DEBUGASSERT(io < K210_IO_NUMBER); - putreg32(ioflags, &fpioa[io]); + putreg32(ioflags, &fpioa_base[io]); }