diff --git a/APP_Framework/Applications/Makefile b/APP_Framework/Applications/Makefile index 0f0d2a744..334845b8a 100644 --- a/APP_Framework/Applications/Makefile +++ b/APP_Framework/Applications/Makefile @@ -36,5 +36,9 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) SRC_DIR += control_app endif + ifeq ($(CONFIG_APP_USING_WEBNET),y) + SRC_DIR += webnet + endif + include $(KERNEL_ROOT)/compiler.mk endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/Kconfig b/APP_Framework/Applications/app_test/Kconfig index c5e5894cd..33b3bc740 100644 --- a/APP_Framework/Applications/app_test/Kconfig +++ b/APP_Framework/Applications/app_test/Kconfig @@ -72,6 +72,24 @@ menu "test app" endif endif + menuconfig USER_TEST_SOCKET + select BSP_USING_LWIP + bool "Config test socket(lwip)" + default n + + menuconfig USER_TEST_UART + select BSP_USING_UART + select BSP_USING_UART6 + bool "Config test uart" + default n + if USER_TEST_UART + if ADD_XIZI_FEATURES + config UART_DEV_DRIVER + string "Set uart dev path" + default "/dev/usart6_dev6" + endif + endif + menuconfig USER_TEST_RS485 select BSP_USING_UART select BSP_USING_GPIO @@ -252,6 +270,10 @@ menu "test app" bool "Config test red black tree" default n + menuconfig USER_TEST_MODBUS_TCP + bool "Config test modbus_tcp" + default n + menuconfig USER_TEST_WEBSERVER bool "Config test webserver" default n diff --git a/APP_Framework/Applications/app_test/Makefile b/APP_Framework/Applications/app_test/Makefile index 10f8129d6..b0a10813e 100644 --- a/APP_Framework/Applications/app_test/Makefile +++ b/APP_Framework/Applications/app_test/Makefile @@ -49,6 +49,10 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) SRC_FILES += test_i2c.c endif + ifeq ($(CONFIG_USER_TEST_UART),y) + SRC_FILES += test_uart.c + endif + ifeq ($(CONFIG_USER_TEST_GPIO),y) SRC_FILES += test_gpio.c endif @@ -111,8 +115,16 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) ifeq ($(CONFIG_USER_TEST_RBTREE),y) SRC_FILES += test_rbtree/test_rbtree.c + endif + + ifeq ($(CONFIG_USER_TEST_SOCKET),y) + SRC_FILES += test_socket.c endif + ifeq ($(CONFIG_USER_TEST_MODBUS_TCP),y) + SRC_DIR += test_modbus_tcp + endif + ifeq ($(CONFIG_USER_TEST_WEBSERVER),y) SRC_FILES += test_webserver/test_webserver.c endif diff --git a/APP_Framework/Applications/app_test/test_adc.c b/APP_Framework/Applications/app_test/test_adc.c index ceceec161..c1b8f66d3 100644 --- a/APP_Framework/Applications/app_test/test_adc.c +++ b/APP_Framework/Applications/app_test/test_adc.c @@ -26,9 +26,8 @@ void TestAdc(void) { int adc_fd; - uint8 adc_channel = 0x0; - uint16 adc_sample, adc_value_decimal = 0; - float adc_value; + uint8 adc_channel = 0x1; + uint16 adc_sample = 0; adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR); if (adc_fd < 0) { @@ -45,13 +44,11 @@ void TestAdc(void) return; } - PrivRead(adc_fd, &adc_sample, 2); - - adc_value = (float)adc_sample * (3.3 / 4096); - - adc_value_decimal = (adc_value - (uint16)adc_value) * 1000; - - printf("adc sample %u value integer %u decimal %u\n", adc_sample, (uint16)adc_value, adc_value_decimal); + for (int i = 0; i < 10; i ++) { + PrivRead(adc_fd, &adc_sample, 2); + printf("adc sample %u mv\n", adc_sample); + PrivTaskDelay(500); + } PrivClose(adc_fd); diff --git a/APP_Framework/Applications/app_test/test_dac.c b/APP_Framework/Applications/app_test/test_dac.c index 37ac2bf1c..8628d1a00 100644 --- a/APP_Framework/Applications/app_test/test_dac.c +++ b/APP_Framework/Applications/app_test/test_dac.c @@ -22,17 +22,16 @@ #include #ifdef ADD_XIZI_FEATURES -void TestDac(void) +static pthread_t test_dac_task; + +static void *TestDacTask(void *parameter) { int dac_fd; - uint16 dac_set_value = 800; - uint16 dac_sample, dac_value_decimal = 0; - float dac_value; + uint16 dac_set_value = 4096 * 10;//sin length dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR); if (dac_fd < 0) { KPrintf("open dac fd error %d\n", dac_fd); - return; } struct PrivIoctlCfg ioctl_cfg; @@ -41,20 +40,24 @@ void TestDac(void) if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) { KPrintf("ioctl dac fd error %d\n", dac_fd); PrivClose(dac_fd); - return; } - PrivRead(dac_fd, &dac_sample, 2); - - dac_value = (float)dac_sample * (3.3 / 4096);//Vref+ need to be 3.3V - - dac_value_decimal = (dac_value - (uint16)dac_value) * 1000; - - printf("dac sample %u value integer %u decimal %u\n", dac_sample, (uint16)dac_value, dac_value_decimal); + while (1) { + //start dac output sin + PrivWrite(dac_fd, NULL, 0); + } PrivClose(dac_fd); +} - return; +void TestDac(void) +{ + pthread_attr_t tid; + tid.schedparam.sched_priority = 20; + tid.stacksize = 4096; + + PrivTaskCreate(&test_dac_task, &tid, &TestDacTask, NULL); + PrivTaskStartup(&test_dac_task); } PRIV_SHELL_CMD_FUNCTION(TestDac, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR); #endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_hwtimer.c b/APP_Framework/Applications/app_test/test_hwtimer.c index 9e6f7f981..9438683f8 100644 --- a/APP_Framework/Applications/app_test/test_hwtimer.c +++ b/APP_Framework/Applications/app_test/test_hwtimer.c @@ -28,11 +28,11 @@ static uint16_t pin_fd=0; static struct PinStat pin_led; -void ledflip(void *parameter) +void LedFlip(void *parameter) { pin_led.pin = BSP_LED_PIN; pin_led.val = !pin_led.val; - PrivWrite(pin_fd,&pin_led,NULL_PARAMETER); + PrivWrite(pin_fd, &pin_led, NULL_PARAMETER); } void TestHwTimer(void) @@ -40,22 +40,22 @@ void TestHwTimer(void) x_ticks_t period = 100000; pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR); - if(pin_fd<0){ + if(pin_fd<0) { printf("open pin fd error:%d\n",pin_fd); return; } int timer_fd = PrivOpen(HWTIMER_TIMER_DEV_DRIVER, O_RDWR); - if(timer_fd<0){ + if(timer_fd<0) { printf("open timer fd error:%d\n",timer_fd); return; } //config led pin in board - struct PinParam parameter; - parameter.cmd = GPIO_CONFIG_MODE; - parameter.pin = BSP_LED_PIN; - parameter.mode = GPIO_CFG_OUTPUT; + struct PinParam parameter; + parameter.cmd = GPIO_CONFIG_MODE; + parameter.pin = BSP_LED_PIN; + parameter.mode = GPIO_CFG_OUTPUT; struct PrivIoctlCfg ioctl_cfg; ioctl_cfg.ioctl_driver_type = PIN_TYPE; @@ -68,7 +68,7 @@ void TestHwTimer(void) } ioctl_cfg.ioctl_driver_type = TIME_TYPE; - ioctl_cfg.args = (void *)&ledflip; + ioctl_cfg.args = (void *)&LedFlip; if (0 != PrivIoctl(timer_fd, OPE_INT, &ioctl_cfg)) { printf("timer pin fd error %d\n", pin_fd); PrivClose(pin_fd); @@ -82,13 +82,10 @@ void TestHwTimer(void) return; } - while(1){ + while(1) { } - // int32 timer_handle = KCreateTimer("LED on and off by 1s",&ledflip,&pin_fd,period,TIMER_TRIGGER_PERIODIC); - - // KTimerStartRun(timer_handle); PrivClose(pin_fd); PrivClose(timer_fd); } diff --git a/APP_Framework/Applications/app_test/test_i2c.c b/APP_Framework/Applications/app_test/test_i2c.c index 76881b92e..a7fb3a060 100644 --- a/APP_Framework/Applications/app_test/test_i2c.c +++ b/APP_Framework/Applications/app_test/test_i2c.c @@ -24,18 +24,16 @@ #define I2C_SLAVE_ADDRESS 0x0012U -void TestI2C(void) +int OpenIic(void) { - // config IIC pin(SCL:34.SDA:35) in menuconfig int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR); if (iic_fd < 0) { - printf("open iic_fd fd error:%d\n", iic_fd); - return; + printf("[TestI2C] Open iic_fd fd error: %d\n", iic_fd); + return -ERROR; } - printf("IIC open successful!\n"); + printf("[TestI2C] IIC open successful!\n"); - // init iic uint16 iic_address = I2C_SLAVE_ADDRESS; struct PrivIoctlCfg ioctl_cfg; @@ -44,28 +42,55 @@ void TestI2C(void) if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg)) { - printf("ioctl iic fd error %d\n", iic_fd); + printf("[TestI2C] Ioctl iic fd error %d\n", iic_fd); PrivClose(iic_fd); - return; + return -ERROR; } printf("IIC configure successful!\n"); - // I2C read and write - char tmp_buff[100]; - while (1) - { - PrivTaskDelay(1000); - PrivWrite(iic_fd, "Hello World!\n", sizeof("Hello World!\n")); - printf("msg send:%s\n", "Hello World!\n"); - PrivTaskDelay(1000); - memset(tmp_buff, 0, sizeof(tmp_buff)); - PrivRead(iic_fd, tmp_buff, sizeof(tmp_buff)); - printf("msg recv:%s\n", tmp_buff); + return iic_fd; +} + +static const int nr_transmit = 15; + +void TestMasterI2c(void) +{ + char recv_buff[13] = { 0 }; + + int iic_fd = OpenIic(); + if (iic_fd < 0) { + printf("[%s] Error open iic\n", __func__); + return; + } + + for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) { + // wait if you like. + PrivTaskDelay(500); + memset(recv_buff, 0, sizeof(recv_buff)); + PrivRead(iic_fd, recv_buff, sizeof(recv_buff)); + printf("[%s] Msg recv: %s\n", __func__, recv_buff); } PrivClose(iic_fd); - return; } -PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR); +void TestSlaveI2c(void) +{ + char send_buff[] = "Hello, World"; + + int iic_fd = OpenIic(); + + for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) { + // wait if you like. + PrivTaskDelay(500); + PrivWrite(iic_fd, send_buff, sizeof(send_buff)); + printf("[%s] Msg send: %s\n", __func__, send_buff); + } + + PrivClose(iic_fd); +} + +PRIV_SHELL_CMD_FUNCTION(TestMasterI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR); +PRIV_SHELL_CMD_FUNCTION(TestSlaveI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR); + #endif \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/Makefile b/APP_Framework/Applications/app_test/test_modbus_tcp/Makefile new file mode 100644 index 000000000..34093f67d --- /dev/null +++ b/APP_Framework/Applications/app_test/test_modbus_tcp/Makefile @@ -0,0 +1,11 @@ +ifeq ($(CONFIG_ADD_XIZI_FEATURES),y) +SRC_FILES := modbus_tcp.c test_modbus_tcp.c +include $(KERNEL_ROOT)/compiler.mk +endif + +include $(KERNEL_ROOT)/.config +ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y) + include $(APPDIR)/Make.defs + CSRCS += modbus_tcp.c test_modbus_tcp.c + include $(APPDIR)/Application.mk +endif diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/README.md b/APP_Framework/Applications/app_test/test_modbus_tcp/README.md new file mode 100644 index 000000000..153cd6d86 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_modbus_tcp/README.md @@ -0,0 +1,340 @@ +# ##modbus-tcp## + +## 1. 简介 + +在xiuos平台实现modbusTCP协议,包括协议报文组装、解析和数据传输,支持主从通信。 + +## 2. 数据结构设计说明 + +### 2.1 数据结构定义 + +首先,需要定义设备存储区的结构体,包括两种存储类型,16位的寄存器和线圈。 + +```c +//定义存储区结构体 +typedef struct MbMemory +{ + coils8_t*rcoil_mem; + reg_t*rreg_mem; + coils8_t*rwcoil_mem; + reg_t*rwreg_mem; +}MBmemoryType; +``` + +​ 然后便是关于ModbusTCP协议相关的结构体定义,包括MBAP和PDU,后续数据区视情况而定,长短不固定。 + +```c +//协议的固定部分为12个字节,当功能码为写多个数据时,后续还有不定长的数据部分 +typedef struct mbap +{ + //MbapType + u16_t tid; + u16_t pid; + u16_t len; + u8_t uid; + + /* data */ +}MbapType; + +typedef struct pdu +{ + u8_t func; + + u16_t addr; + + u8_t operand1; + u8_t operand2; + /* data */ +}PduType; +``` + +### 2.1 从设备请求解析和响应部分 + +​ 主要定义请求的解析器结构,以及每种功能码对应的解析函数,和发送响应的函数。 + +```c +//定义解析器结构体 +typedef struct mbparser +{ + int (*func_set[20])(MBmemoryType*,int,MbapType*,PduType*,u8_t**resp); +}MbParserType; + +//功能码解析函数 +int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); + + +/** + * @description: 制作响应报文 + * @param {MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len} + * @return {} + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +void MakeResponse(MbapType*,PduType*,u8_t**,u16_t); + +/** + * @Description: 发送响应报文 + * @param {int} fd 套接字对应文件描述符 + * @param {u16_t} n 报文大小 + * @return {int} + * @Date: 2023-07-25 17:24:55 + * @Author: pgh_dd 1041315949@qq.com + */ +int SendResponse(int fd,u8_t**buf,u16_t n); + + +``` + +### 2.2 主设备的请求包装和发送部分 + +```c +/** + * @Description: 读取键盘输入,并生成请求报文 + * @param {u8_t} flag + * @return {int} + * @Date: 2023-07-25 17:25:26 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int GenerateModbusRequest(MbapType*,PduType*,u8_t flag,u8_t**request); + +/** + * @Description: 发送请求报文 + * @param {int fd,u8_t**request,int n} + * @return {} + * @Date: 2023-07-25 17:26:10 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +void SendModbus(int fd,u8_t**request,int n); + +/** + * @Description: 读取请求报文 + * @param {int fd,MbapType*mbap,PduType*pdu} + * @return {void} + * @Date: 2023-07-25 17:26:49 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +void GetRequest(int fd,MbapType*,PduType*); +``` + + + +## 3. 测试程序说明 + +​ modbusTCP协议基于TCP协议,因此其主从通信实际上是基于TCP的S/C通信,因此分为服务端和客户端。 + +​ 服务端部分(从设备)程序实际上是一个被动接受请求报文的TCP服务器程序,除了一些基础参数的定义外,主要包括一个无限循环的服务程序,包括报文的接收,以及对存储区的操作,和生成发送响应。 + +```c +static void *ModbusTcpServer(void *arg) +{ + //设置IP和子网掩码网关 + u8_t uid=1;//定义从设备id和存储区 + + MBmemory mbm;//定义存储区 + if(mb_memory_init(&mbm)==-1)//初始化存储区,包括对四个存储区进行内存分配 + { + return 0; + }; + + MBparser mb_parser;//初始化功能码解析器 + MBparser_init(&mb_parser,MBTCP);//初始化解析器,将功能码对应函数注册 + + int fd=create_socket(PORT);//创建监听套接字 + if(fd==-1)return 0; + + if (listen(fd, 10) != 0 ) { + lw_error("Unable to listen\n"); + close(fd); + return 0; + } + + while(1) + { + //建立连接,因为每次接受的连接可能不是同一个设备发来的,因此需要把建立连接部分放在循环体内。 + struct sockaddr_in tcp_addr; + socklen_t addr_len; + + printf("wait accept\n"); + int clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); + + if(clientfd==-1) + { + lw_error("Unable to listen\n"); + return 0; + } + + while(1) + { + MBAP mbap; + PDU pdu; + read_mbtcp_MBAP(clientfd,&mbap);//读取数据前7字节为mbap初始化 + + if(mbap.uid!=uid){//检验是否为此从机 + close(clientfd); + break; + } + + + read_mbtcp_PDU(clientfd,&pdu);//读取pdu和一些定长部分 + + printf("OP:%x\n",pdu.func); + printf("ADDR:%x\n",pdu.addr); + + u8_t** response_buf;//定义操作返回的指针 + u8_t buf_len=mb_parser.func_set[pdu.func](&mbm,clientfd,&mbap,&pdu,response_buf);//请求的解析和对存储区的操作 + + send_response(clientfd,response_buf,buf_len);//发送响应 + // return NULL; + //执行操作 + + } + close(clientfd); + } + close(fd); + mb_memory_free(&mbm);//释放存储区 +} + +``` + +​ 客户端部分(主设备)是一个主动发送请求的TCP客户端程序,主要包括一个接受键盘输入的循环体,可以接受用户输入的指令,然后包装成Modbus请求报文,并发送给ModbusTCP服务器,然后接受响应报文。 + +```c +static void *ModbusTcpClient(void *arg) +{ + u16_t counter=0; + int fd = -1; + int ret; + + // lw_print("2023-05-27 Peng Guanhua\n"); + lw_print("%s start\n", __func__); + + fd = socket(AF_INET, SOCK_STREAM, 0);//定义服务器套接字 + if (fd < 0) { + lw_print("Socket error\n"); + return NULL; + } + + char tcp_ip_str[128]="192.168.31.148";//服务器ip和端口号 + u16_t tcp_socket_port=6000; + + /*建立套接字连接*/ + printf("%s\n",tcp_ip_str); + struct sockaddr_in tcp_sock; + tcp_sock.sin_family = AF_INET; + tcp_sock.sin_port = htons(tcp_socket_port); + tcp_sock.sin_addr.s_addr = inet_addr(tcp_ip_str); + printf("%s\n",tcp_ip_str); + + memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); + + ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr)); + + if (ret < 0) { + lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret); + close(fd); + return NULL; + } + + lw_print("TCP connect %s:%d success, start.\n", tcp_ip_str, tcp_socket_port); + + + + while (1) { + + MBAP mbap={counter,0,0,0}; + PDU pdu; + u8_t*request; + + int mesg_len=generate_modbus_request(&mbap,&pdu,MBTCP,&request);//此函数中接收键盘输入,并生成请求报文。 + send_modbus(fd,&request,mesg_len);//发送请求报文。 + get_response(fd,&mbap,&pdu);//接收响应报文,并显示 + counter++; + } + + close(fd); + return NULL; +} +``` + + + +## 4. 运行结果 + +### 4.1 从设备通信测试 + +从设备测试,在终端上将TCP服务端程序打开,如图1,等待主设备的连接。 + +![alt 图1从设备等到主设备连接](./img/modbusTCP_S1.png) + +​ 主设备采用Modbus Poll应用程序,建立TCP连接,如图2所示。 + +![alt 图2主设备与从设备建立TCP连接](./img/modbusTCP_S2.png) + +​ 此时modbus poll程序便会不断的向从设备发送请求,如图3。 + +![alt 图3从设备接收从设备请求报文并响应](./img/modbusTCP_S3.png) + +​ 可以看到解析出的功能码、地址以及对应的响应报文,然后我们在modbus poll上修改一下存储区数据。如图4所示。 + +![alt 图4](./img/modbusTCP_S4.png) + +因为修改的是寄存器存储区的值,因此对应0x10功能码,然后看看从设备的反映。如图5所示。 + +![alt 图5](./img/modbusTCP_S6.png) + +可见成功收到功能码,并返回了响应的报文。 + +![alt 图6](./img/modbusTCP_S5.png) + +modbus poll显示响应成功,存储区已成功修改期望的值。 + +![alt 图7](./img/modbusTCP_S7.png) + +可见存储区已成功修改。 + +线圈部分的查询修改同理,不再赘述。 + +### 4.2主设备通信测试 + +​ 首先打开modbus slave应用程序,用以作为从设备,然后将存储区数据修改,用以测试,并打开TCP端口,等待主设备的连接,如图8所示。 + +![alt 图8](./img/modbusTCP_C2.png) + +​ 同样在终端打开从设备程序,从设备的ip,port在源码中已定义好,所以打开时已经连接上,如图9所示。 + + + +![alt 图9](./img/modbusTCP_C1.png) + +​ 开始输入从设备id,功能码,以及其他信息用以生成请求报文。 + +![alt 图10](./img/modbusTCP_C3.png) + +​ 如图10所示,输入功能码3,对应读取寄存器功能,地址从0开始,数量4,然后便会生成请求报文,然后发送,结果如图11所示。 + +![alt](./img/modbusTCP_C4.png) + +​ 可见,已成功查询到寄存器的值。 + +​ 然后测试写入功能,输入功能码15(0xf),对应写入多个线圈功能,如图12,modbus slave对应的响应结果如图13所示。 + +​ ![alt 图12](./img/modbusTCP_C5.png) + +​ 写入线圈的值为5个,分别为1 0 1 0 1。发送成功后,modbus salve中显示如图13所示。 + +![alt 图13](./img/modbusTCP_C6.png) + +​ 可见,已成功修改。 + +​ 其他功能码测试过程类似,不再赘述。 \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C1.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C1.png new file mode 100644 index 000000000..5561b12c4 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C1.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C2.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C2.png new file mode 100644 index 000000000..86ae5e38a Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C2.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C3.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C3.png new file mode 100644 index 000000000..89a1b8d93 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C3.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C4.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C4.png new file mode 100644 index 000000000..7f9af533d Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C4.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C5.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C5.png new file mode 100644 index 000000000..da5319285 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C5.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C6.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C6.png new file mode 100644 index 000000000..9f9c230ec Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_C6.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S1.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S1.png new file mode 100644 index 000000000..174c7d1f8 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S1.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S2.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S2.png new file mode 100644 index 000000000..247be62ed Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S2.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S3.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S3.png new file mode 100644 index 000000000..7a15f8800 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S3.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S4.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S4.png new file mode 100644 index 000000000..4d8bf1a0e Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S4.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S5.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S5.png new file mode 100644 index 000000000..31ad122b8 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S5.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S6.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S6.png new file mode 100644 index 000000000..f06a4bf29 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S6.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S7.png b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S7.png new file mode 100644 index 000000000..fdbec3295 Binary files /dev/null and b/APP_Framework/Applications/app_test/test_modbus_tcp/img/modbusTCP_S7.png differ diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/modbus_tcp.c b/APP_Framework/Applications/app_test/test_modbus_tcp/modbus_tcp.c new file mode 100644 index 000000000..7e7f57ee4 --- /dev/null +++ b/APP_Framework/Applications/app_test/test_modbus_tcp/modbus_tcp.c @@ -0,0 +1,729 @@ +/* +* Copyright (c) 2020 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. +*/ + +/* + * @Description:包含modbusTCP请求报文的包装解析,以及报文收发,和每种功能码对应操作的实现。 + * @Version: V1.0.0 + * @Author: pgh_dd 1041315949@qq.com + * @Date: 2023-05-24 04:00:02 + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 16:36:53 + */ + + + +#include"modbus_tcp.h" + +u16_t Func0x_response_length[20]= +{ + 0,9,9,9,9,12,12,0,0,0,0,0,0,0,0,12,12 +}; + + +/** + * @description: 初始化功能码解析器 + * @param {MbParserType*}mbp {u8_t} type + * @return {void} + * @Date: 2023-07-25 16:59:23 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +void MbparserInit(MbParserType*mbp,u8_t type) +{ + mbp->func_set[R_RW_COIL]=FuncReadRwCoilX01; + mbp->func_set[R_R_COIL]=FuncReadRCoilX02; + mbp->func_set[R_RW_REG]=FuncReadRwRegX03; + mbp->func_set[R_R_REG]=FuncReadRRegX04; + mbp->func_set[W_RW_COIL]=FuncWriteRwCoilX05; + mbp->func_set[W_RW_REG]=FuncWriteRwRegX06; + mbp->func_set[W_MRW_REG]=FuncWriteRwMregsX10; + mbp->func_set[W_MRW_COIL]=FuncWriteRwMcoilsX0f; + mbp->func_set[REPORT_SlAVE_ID]=FuncReportSlaveIDX11; +}; + + +/** + * @description:初始化存储区 + * @return {int} + * @Date: 2023-07-25 17:01:47 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +int MbMemoryInit(MBmemoryType*mbm) +{ + mbm->rcoil_mem=(coils8_t*)malloc(sizeof(coils8_t)*RCOILMEM); + mbm->rreg_mem=(reg_t*)malloc(sizeof(reg_t)*RREGMEM); + mbm->rwcoil_mem=(coils8_t*)malloc(sizeof(coils8_t)*RWCOILMEM); + mbm->rwreg_mem=(reg_t*)malloc(sizeof(reg_t)*RWREGMEM); + + memset(mbm->rwreg_mem,0,RWREGMEM); + memset(mbm->rreg_mem,0,RREGMEM); + memset(mbm->rcoil_mem,0,RCOILMEM); + memset(mbm->rwcoil_mem,0,RWCOILMEM); + + // mbm->rwreg_mem[0]=3; + // mbm->rwreg_mem[1]=0x30ff; + mbm->rwcoil_mem[0]=1;mbm->rwcoil_mem[2]=1;mbm->rwcoil_mem[4]=1; + + if(mbm->rcoil_mem==NULL||mbm->rreg_mem==NULL||mbm->rwcoil_mem==NULL||mbm->rwreg_mem==NULL) + { + lw_error("memory is not full\n"); + return -1; + } + return 0; +} + +/** + * @description: 释放存储区 + * @return {void} + * @Date: 2023-07-25 17:02:22 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +void MbMemoryFree(MBmemoryType*mbm) +{ + free(mbm->rcoil_mem); + free(mbm->rreg_mem); + free(mbm->rwcoil_mem); + free(mbm->rwreg_mem); +} + +/** + * @description: 创建tcp通信套接字 + * @param {int} port + * @return {int} + * @Date: 2023-07-25 17:02:39 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +int CreateSocket(int port) +{ + int fd = -1, clientfd; + fd = socket(AF_INET, SOCK_STREAM, 0); + if(fd==-1)return -1; + int recv_len; + char *recv_buf; + struct sockaddr_in tcp_addr; + socklen_t addr_len; + + tcp_addr.sin_family = AF_INET; + tcp_addr.sin_addr.s_addr = INADDR_ANY; + tcp_addr.sin_port = htons(port); + memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero)); + + if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) { + lw_error("Unable to bind\n"); + close(fd); + return -1; + } + + lw_print("tcp bind success, start to receive.\n"); + lw_notice("\nLocal Port:%d\n", port); + + // setup socket fd as listening mode + if (listen(fd,128) != 0 ) { + lw_error("Unable to listen\n"); + close(fd); + return -1; + } + lw_print("Tcp start to listen.\n"); + return fd; +} + +/** + * @description: 读取请求报文的MBAP头部分 + * @param {int} fd {MbapType*}mbap + * @return {} + * @Date: 2023-07-25 17:03:04 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +int ReadMbtcpMBAP(int fd,MbapType*mbap) +{ + char buf[MODBUS_MBAP]; + read(fd,buf,MODBUS_MBAP); + mbap->tid=(((u16_t)buf[0])<<8)+(u16_t)buf[1];//高位左移8位再加低位 + mbap->pid=(((u16_t)buf[2])<<8)+(u16_t)buf[3]; + mbap->len=(((u16_t)buf[4])<<8)+(u16_t)buf[5]; + mbap->uid=((u8_t)buf[6]); + +}; + +/** + * @description: 读取请求报文的PDU部分 + * @param {int} fd {PduType*}pdu + * @return {} + * @Date: 2023-07-25 17:03:04 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +int ReadMbtcpPDU(int fd,PduType*pdu) +{ + char buf[MODBUS_PDUHEAD]; + + int n=read(fd,buf,MODBUS_PDUHEAD); + + + pdu->func=(u8_t)buf[0];//高位左移8位再加低位 + + if(n>3) + { + pdu->addr=(((u16_t)buf[1])<<8)+(u16_t)buf[2]; + pdu->operand1=(u8_t)buf[3]; + pdu->operand2=(u8_t)buf[4]; + } +}; + +/** + * @description: 制作响应报文 + * @param {MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len} + * @return {} + * @Date: 2023-07-25 17:11:23 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +void MakeResponse(MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len) +{ + buf_len-=6; + //这个长度实际是从数据长度位置到结束的长度,因此要将响应报文的总长减去事务头、协议、长度三个两字节数共6个 + (*resp)[0]=(u8_t)(mbap->tid>>8);(*resp)[1]=(u8_t)(0xff&mbap->tid); + (*resp)[2]=(u8_t)(mbap->pid>>8);(*resp)[3]=(u8_t)(0xff&mbap->pid); + (*resp)[4]=(u8_t)(buf_len>>8);(*resp)[5]=(u8_t)(0xff&buf_len); + (*resp)[6]=mbap->uid; + (*resp)[7]=pdu->func; +} + + +/** + * @description: 功能码0x1,负责读取从设备线圈的状态 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {} + * @Date: 2023-07-25 17:12:00 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + * @LastEditTime: 2023-07-25 17:10:31 + */ +int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x01\n"); + printf("coils num:%d\n"); + u16_t coils_num=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;//线圈个数 + u16_t bytes_num=(coils_num/8+((coils_num%8)!=0));//输出的字节长度 + u16_t buf_len=Func0x_response_length[R_RW_COIL]+bytes_num;//response报文所占长度 + + *resp=(u8_t*)malloc(buf_len); memset(*resp,0,buf_len); + MakeResponse(mbap,pdu,resp,buf_len); + (*resp)[8]=(u8_t)bytes_num; + u8_t*sub_mem=mem->rwcoil_mem; + for(int i=0;iaddr]==1?((u8_t)1<<(i%8)):0); + } + + return buf_len; + // u8_t +}; + +/** + * @Description: 0x2功能码,读离散输入状态 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {} + * @Date: 2023-07-25 17:20:13 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x02\n"); + + u16_t coils_num=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;//线圈个数 + u16_t bytes_num=(coils_num/8+((coils_num%8)!=0));//输出的字节长度 + u16_t buf_len=Func0x_response_length[R_RW_COIL]+bytes_num;//response报文所占长度 + + *resp=(u8_t*)malloc(buf_len); memset(*resp,0,buf_len); + MakeResponse(mbap,pdu,resp,buf_len); + (*resp)[8]=(u8_t)bytes_num; + u8_t*sub_mem=mem->rcoil_mem; + for(int i=0;iaddr]==1?((u8_t)1<<(i%8)):0); + } + + return buf_len; +}; + + +/** + * @Description: 读保持寄存器 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {} + * @Date: 2023-07-25 17:21:01 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x03\n"); + u16_t data_len=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2; + + u16_t buf_len=Func0x_response_length[R_RW_REG]+data_len*2; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)data_len*2; + + u16_t*sub_mem=mem->rwreg_mem; + + u16_t addr_mem=pdu->addr,addr_resp=9; + int c=0; + while(c>8); + (*resp)[addr_resp+1]=(u8_t)(sub_mem[addr_mem]&0xff); + addr_resp+=2;addr_mem++; + c++; + } + + return buf_len; +}; + +/** + * @Description: 0x4功能码,读输入寄存器 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {} + * @Date: 2023-07-25 17:21:22 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x04\n"); + u16_t data_len=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2; + + u16_t buf_len=Func0x_response_length[R_R_REG]+data_len*2; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)data_len*2; + + u16_t*sub_mem=mem->rreg_mem; + + u16_t addr_mem=pdu->addr,addr_resp=9; + + int c=0; + while(c>8); + (*resp)[addr_resp+1]=(u8_t)(sub_mem[addr_mem]&0xff); + addr_resp+=2;addr_mem++; + c++; + } + + return buf_len; +}; + +/** + * @Description: 0x5功能码,写单个线圈 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {int} + * @Date: 2023-07-25 17:21:51 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x05\n"); + u16_t addr_coil=pdu->addr; + u16_t operand=(((u16_t)pdu->operand1)<<8)+(u16_t)pdu->operand2; + if(operand==0xff00||operand==0x0000) + { + mem->rwcoil_mem[addr_coil]=(operand==0xff00?1:0); + } + + u16_t buf_len=Func0x_response_length[W_RW_COIL]; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)((pdu->addr)>>8); + (*resp)[9]=(u8_t)(pdu->addr&0xff); + (*resp)[10]=(u8_t)(pdu->operand1); + (*resp)[11]=(u8_t)(pdu->operand2); + + printf("write data:%x\n",operand); + + return buf_len; + +}; + +/** + * @Description: 0x6功能码,写单个保持寄存器 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {int} + * @Date: 2023-07-25 17:22:38 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x06\n"); + u16_t addr_reg=pdu->addr; + u16_t reg_data=(u16_t)((pdu->operand1)<<8)+(u16_t)(pdu->operand2); + mem->rwreg_mem[addr_reg]=reg_data; + u16_t buf_len=Func0x_response_length[W_RW_REG]; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)((pdu->addr)>>8); + (*resp)[9]=(u8_t)(pdu->addr&0xff); + (*resp)[10]=(u8_t)(pdu->operand1); + (*resp)[11]=(u8_t)(pdu->operand2); + + printf("write data:%x\n",reg_data); + return buf_len; +}; + +/** + * @Description: 0xf功能码,写多个线圈 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {int} + * @Date: 2023-07-25 17:23:16 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x0f\n"); + u16_t coils_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2); + + u16_t res_num=coils_num/8+(coils_num%8!=0)+1; + + u8_t*recv_buf=(u8_t*)malloc(sizeof(u8_t)*res_num); + + int n=read(fd,(char*)recv_buf,res_num); + + + u8_t*sub_mem=mem->rwcoil_mem; + + for(int i=0;iaddr+i]=((recv_buf[1+i/8]&(1<<(i%8)))==0?0:1); + } + + + u16_t buf_len=Func0x_response_length[W_MRW_COIL]; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)((pdu->addr)>>8); + (*resp)[9]=(u8_t)(pdu->addr&0xff); + (*resp)[10]=(u8_t)(pdu->operand1); + (*resp)[11]=(u8_t)(pdu->operand2); + + free(recv_buf); + + + + return buf_len; +}; + +/** + * @Description: 0x10功能码,写多个保持寄存器 + * @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp} + * @return {int} + * @Date: 2023-07-25 17:23:56 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x10\n"); + u16_t data_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2); + u16_t res_num=data_num*2+1; + u8_t*recv_buf=(u8_t*)malloc(sizeof(u8_t)*res_num); + + + int n=read(fd,(char*)recv_buf,res_num); + + // printf("%x %x %x\n",recv_buf[0],recv_buf[1],recv_buf[2]); + + u16_t*sub_mem=mem->rwreg_mem; + + for(int i=0;iaddr+i]=(((u16_t)(recv_buf[1+i*2]))<<8)+(u16_t)(recv_buf[1+i*2+1]); + } + + + u16_t buf_len=Func0x_response_length[W_MRW_REG]; + *resp=(u8_t*)malloc(buf_len); + + MakeResponse(mbap,pdu,resp,buf_len); + + (*resp)[8]=(u8_t)((pdu->addr)>>8); + (*resp)[9]=(u8_t)(pdu->addr&0xff); + (*resp)[10]=(u8_t)(pdu->operand1); + (*resp)[11]=(u8_t)(pdu->operand2); + + + free(recv_buf); + + return buf_len; +}; + +/** + * @Description: 报告从设备id + * @param {int} fd + * @return {} + * @Date: 2023-07-25 17:24:43 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp) +{ + printf("enter x11\n"); + +}; + +/** + * @Description: 发送响应报文 + * @param {int} fd + * @param {u16_t} n + * @return {} + * @Date: 2023-07-25 17:24:55 + * @Author: pgh_dd 1041315949@qq.com + * @LastEditors: pgh_dd 1041315949@qq.com + */ +int SendResponse(int fd,u8_t**buf,u16_t n) +{ + printf("Response:"); + for(int i=0;iuid);printf("%d",mbap->uid);printf("\n"); + + printf("Please input function code:"); + scanf("%x",&pdu->func);printf("%x",pdu->func);printf("\n"); + + printf("The address:"); + scanf("%d",&pdu->addr);printf("%d",pdu->addr);printf("\n"); + + switch (pdu->func) + { + case R_RW_COIL: + case R_R_COIL:printf("The number of coils you want read:");break; + case R_RW_REG: + case R_R_REG:printf("The number of registers you want read:");break; + + case W_RW_COIL:printf("The value of coil you want write(1 or 0):");break; + case W_RW_REG:printf("The value of register you want write:");break; + + case W_MRW_COIL:printf("The number of coils you want write:");break; + case W_MRW_REG:printf("The number of registers you want write:");break; + + default: + break; + } + u16_t num; + scanf("%d",&num);printf("%d\n",num); + if(pdu->func==W_RW_COIL) + { + pdu->operand2=0; + pdu->operand1=(num==1?0xff:0); + } + else { + pdu->operand1=(u8_t)(num>>8); + pdu->operand2=(u8_t)(num&0x00ff); + } + + + if(pdu->func==W_MRW_REG) + { + send_buf_length=num*2+1+12; + *request=(u8_t*)malloc(send_buf_length); + memset(*request,0,send_buf_length); + printf("input register data(decimal integer,in total %d):",num); + (*request)[12]=(u8_t)(num*2); + for(int i=0;i>8); + (*request)[i*2+13+1]=(u8_t)(tem&0x00ff); + } + printf("\n"); + } + else if(pdu->func==W_MRW_COIL) + { + send_buf_length=num/8+(num%8!=0)+1+12; + *request=(u8_t*)malloc(send_buf_length); + memset(*request,0,send_buf_length); + printf("input coil data(0 or 1,in total %d):",num); + (*request)[12]=(u8_t)(num/8+(num%8!=0)); + for(int i=0;iaddr]==1?((u8_t)1<<(i%8)):0); + } + } + printf("\n"); + } + else + { + send_buf_length=12; + *request=(u8_t*)malloc(send_buf_length); + if((*request)==NULL)printf("erro\n"); + + } + + (*request)[0]=(u8_t)(mbap->tid>>8);(*request)[1]=(u8_t)(0xff&mbap->tid); + (*request)[2]=(u8_t)(mbap->pid>>8);(*request)[3]=(u8_t)(0xff&mbap->pid); + (*request)[4]=(u8_t)((send_buf_length-6)>>8);(*request)[5]=(u8_t)(0xff&(send_buf_length-6)); + (*request)[6]=mbap->uid; + (*request)[7]=pdu->func; + (*request)[8]=(u8_t)(pdu->addr>>8);(*request)[9]=(u8_t)(0xff&pdu->addr); + (*request)[10]=pdu->operand1;(*request)[11]=pdu->operand2; + + printf("messege is:"); + for(int i=0;ifunc,1);//读取功能码 + + u8_t byte_num=0; + u8_t *recv_buf; + switch (pdu->func) + { + case R_R_COIL: + case R_R_REG: + case R_RW_COIL: + case R_RW_REG: + data_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2); + read(fd,&byte_num,1); + recv_buf=(u8_t*)malloc(byte_num); + read(fd,recv_buf,byte_num); + /* code */ + break; + case W_RW_COIL: + case W_RW_REG: + case W_MRW_REG: + case W_MRW_COIL: + recv_buf=(u8_t*)malloc(4); + read(fd, recv_buf,4); + break; + default: + break; + } + + printf("Response: TID:%x func code:%x byte num:%x\n",mbap->tid,pdu->func,byte_num); + + if(pdu->func==R_R_COIL||pdu->func==R_RW_COIL) + { + printf("coils:"); + for(int i=0;ifunc==R_R_REG||pdu->func==R_RW_REG) + { + printf("registers:"); + // for(int i=0;i +#include +#include +#include +#include +#include "lwip/sys.h" + +#define PORT 8888 +#define RCOILMEM 1000 +#define RREGMEM 1000 +#define RWCOILMEM 1000 +#define RWREGMEM 1000 + +#define MBTCP 1 +#define MBRTU 2 +//功能码 +#define R_RW_COIL 0x01 +#define R_R_COIL 0x02 +#define R_RW_REG 0x03 +#define R_R_REG 0x04 +#define W_RW_COIL 0x05 +#define W_RW_REG 0x06 +#define DIAGNOSTIC 0x08 +#define GET_COUNTER 0x0B +#define W_MRW_COIL 0x0F +#define W_MRW_REG 0x10 +#define REPORT_SlAVE_ID 0x11 + + +typedef u8_t coils8_t; +typedef u16_t reg_t; + +#define MODBUS_MBAP 7 +#define MODBUS_PDUHEAD 5 + + +//定义存储区结构体 +typedef struct MbMemory +{ + coils8_t*rcoil_mem; + reg_t*rreg_mem; + coils8_t*rwcoil_mem; + reg_t*rwreg_mem; +}MBmemoryType; +//初始化存储区的函数 +int MbMemoryInit(MBmemoryType*mb); +//释放存储区 +void MbMemoryFree(MBmemoryType*mb); + + +//协议的固定部分为12个字节,当功能码为写多个数据时,后续还有不定长的数据部分 +typedef struct mbap +{ + //MbapType + u16_t tid; + u16_t pid; + u16_t len; + u8_t uid; + + /* data */ +}MbapType; + +typedef struct pdu +{ + u8_t func; + + u16_t addr; + + u8_t operand1; + u8_t operand2; + /* data */ +}PduType; + +int CreateSocket(int port); + +int ReadMbtcpMBAP(int fd,MbapType*mb_s); +int ReadMbtcpPDU(int fd,PduType*mb_s); + + +//操作函数 + +int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); + +int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp); +//位地址转换字节地址 + +//定义解析器结构体 +typedef struct mbparser +{ + int (*func_set[20])(MBmemoryType*,int,MbapType*,PduType*,u8_t**resp); +}MbParserType; +//解析器初始化,实际上就是每个功能码对应的操作函数的注册 +void MbparserInit(MbParserType*mbp,u8_t flag); + +void MakeResponse(MbapType*,PduType*,u8_t**,u16_t); + +int SendResponse(int fd,u8_t**buf,u16_t n); + + +// void func(PDU*pdu); + +// void delete_modbus_request(); +//主机程序 +int GenerateModbusRequest(MbapType*,PduType*,u8_t flag,u8_t**request); + +void SendModbus(int fd,u8_t**request,int n); + +void GetRequest(int fd,MbapType*,PduType*); +#endif diff --git a/APP_Framework/Applications/app_test/test_modbus_tcp/test_modbus_tcp.c b/APP_Framework/Applications/app_test/test_modbus_tcp/test_modbus_tcp.c new file mode 100644 index 000000000..b0565511d --- /dev/null +++ b/APP_Framework/Applications/app_test/test_modbus_tcp/test_modbus_tcp.c @@ -0,0 +1,248 @@ +/* +* 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 lwip_tcp_socket_demo.c +* @brief TCP socket demo based on LwIP +* @version 1.0 +* @author AIIT XUOS Lab +* @date 2022-03-21 +*/ + +#include +#include"modbus_tcp.h" + +#ifdef ADD_XIZI_FEATURES +#include +#include +#include "lwip/sys.h" +#endif + +#ifdef ADD_NUTTX_FEATURES +#include +#include +#include +#include "stdio.h" +#endif + +#define TCP_DEMO_BUF_SIZE 65535 +#define TCP_DEMO_SEND_TIMES 20 +#define LWIP_TCP_DEMO_TASK_STACK_SIZE 4096 +#define LWIP_TCP_DEMO_TASK_PRIO 20 + +static pthread_t tcp_client_task; +static pthread_t tcp_server_task; + +static char tcp_demo_ipaddr[] = {192, 168, 31, 77}; +static char tcp_demo_netmask[] = {255, 255, 255, 0}; +static char tcp_demo_gwaddr[] = {192, 168, 31, 1}; + +#ifdef ADD_NUTTX_FEATURES +#define lw_print printf +#define lw_notice printf +#define lw_error printf + +#define LWIP_DEMO_TIMES 3 +#define LWIP_TARGET_PORT 4840 +#endif + +static uint16_t tcp_socket_port = 8888; +static char tcp_ip_str[128] = {0}; + +/******************************************************************************/ +static void TcpSocketConfigParam(char *ip_str) +{ + int ip1, ip2, ip3, ip4, port = 0; + + if(ip_str == NULL) + return; + + if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) { + printf("config ip %s port %d\n", ip_str, port); + strcpy(tcp_ip_str, ip_str); + if(port) + tcp_socket_port = port; + return; + } + + if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) { + printf("config ip %s\n", ip_str); + strcpy(tcp_ip_str, ip_str); + } +} + +static void *ModbusTcpServer(void *arg) +{ + + u8_t uid=1;//定义从设备id和存储区 + + MBmemoryType mbm;//定义存储区 + if(MbMemoryInit(&mbm)==-1)//初始化存储区,包括对四个存储区进行内存分配 + { + return 0; + }; + + MbParserType mb_parser;//初始化功能码解析器 + MbparserInit(&mb_parser,MBTCP);//初始化解析器,将功能码对应函数注册 + + int fd=CreateSocket(PORT);//创建监听套接字 + if(fd==-1)return 0; + + int recv_len; + char *recv_buf; + struct sockaddr_in tcp_addr; + socklen_t addr_len; + + while(1) + { + struct sockaddr_in tcp_addr; + socklen_t addr_len; + + printf("wait accept\n"); + int clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len); + + if(clientfd==-1) + { + lw_error("Unable to listen\n"); + return 0; + } + + while(1) + { + MbapType mbap; + PduType pdu; + ReadMbtcpMBAP(clientfd,&mbap);//读取数据前7字节为mbap初始化 + + if(mbap.uid!=uid){//检验是否为此从机 + close(clientfd); + break; + } + + + ReadMbtcpPDU(clientfd,&pdu);//读取pdu和一些定长部分 + + printf("OP:%x\n",pdu.func); + printf("ADDR:%x\n",pdu.addr); + + u8_t* response_buf;//定义操作返回的指针 + u8_t buf_len=mb_parser.func_set[pdu.func](&mbm,clientfd,&mbap,&pdu,&response_buf); + + SendResponse(clientfd,&response_buf,buf_len); + // return NULL; + //执行操作 + + } + close(clientfd); + } + close(fd); + MbMemoryFree(&mbm);//释放存储区 +} + +void TestModbusTcpServer(int argc, char *argv[]) +{ + if(argc >= 2) { + lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); + TcpSocketConfigParam(argv[1]); + } + +#ifdef ADD_XIZI_FEATURES + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + +#endif + +#ifdef ADD_NUTTX_FEATURES + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; +#endif + + ModbusTcpServer(NULL); +} + +PRIV_SHELL_CMD_FUNCTION(TestModbusTcpServer, a modbusS test sample, PRIV_SHELL_CMD_MAIN_ATTR); + +static void *ModbusTcpClient(void *arg) +{ + u16_t counter=0; + int fd = -1; + int ret; + + // lw_print("2023-05-27 Peng Guanhua\n"); + lw_print("%s start\n", __func__); + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) { + lw_print("Socket error\n"); + return NULL; + } + + char tcp_ip_str[128]="192.168.31.148"; + u16_t tcp_socket_port=6000; + + + printf("%s\n",tcp_ip_str); + struct sockaddr_in tcp_sock; + tcp_sock.sin_family = AF_INET; + tcp_sock.sin_port = htons(tcp_socket_port); + tcp_sock.sin_addr.s_addr = inet_addr(tcp_ip_str); + printf("%s\n",tcp_ip_str); + + memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero)); + + ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr)); + + if (ret < 0) { + lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret); + close(fd); + return NULL; + } + + lw_print("TCP connect %s:%d success, start.\n", tcp_ip_str, tcp_socket_port); + + + while (1) { + + MbapType mbap={counter,0,0,0}; + PduType pdu; + u8_t*request; + + int mesg_len=GenerateModbusRequest(&mbap,&pdu,MBTCP,&request); + SendModbus(fd,&request,mesg_len); + GetRequest(fd,&mbap,&pdu); + counter++; + } + + close(fd); + return NULL; +} + +void TestModbusTcpClient(int argc, char *argv[]) +{ + if(argc >= 2) { + lw_print("lw: [%s] target ip %s\n", __func__, argv[1]); + TcpSocketConfigParam(argv[1]); + } + +#ifdef ADD_XIZI_FEATURES + lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr); + +#endif +#ifdef ADD_NUTTX_FEATURES + pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER; + attr.priority = LWIP_TCP_DEMO_TASK_PRIO; + attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE; +#endif + + ModbusTcpClient(NULL); +} +PRIV_SHELL_CMD_FUNCTION(TestModbusTcpClient, a modbustcpC test sample, PRIV_SHELL_CMD_MAIN_ATTR); + diff --git a/APP_Framework/Applications/app_test/test_radix_tree/README.md b/APP_Framework/Applications/app_test/test_radix_tree/README.md index b2bfe9cb9..fb4efcb6f 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/README.md +++ b/APP_Framework/Applications/app_test/test_radix_tree/README.md @@ -9,13 +9,15 @@ 基数树节点设计为: ```c -typedef struct _node { -​ void* value; -​ struct _node* next[NODE_SIZE]; -} node; +typedef struct radix_node +{ + void *value; + struct radix_node *child[NODE_SIZE]; + struct radix_node *parent; +} radix_node; ``` -其中,节点在树中的路径即为键,`value` 存储值,`NODE_SIZE` 定义为 128,足以容纳所有 ASCII 值。 +其中,节点在树中的路径即为键,为`unsigned int`类型,`value` 存储值,`NODE_SIZE` 定义为 4,即每个树节点包含2个bit位,可以根据实际需求调整。 一共实现了 5 个函数,分别为: @@ -32,20 +34,19 @@ typedef struct _node { 测试程序定义了以下键值对: ```c -char keys[][MAX_WORD_LEN] = { +char values[][16] = { "what", "where", "why", "how", "hello!", "apple", - "12345" -}; -int values[] = {1, 2, 3, 4, 5, 6, 7}; + "12345"}; +unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7}; ``` 1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到 -2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到 +2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个值的键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到 3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到 4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到 diff --git a/APP_Framework/Applications/app_test/test_radix_tree/fig6.png b/APP_Framework/Applications/app_test/test_radix_tree/fig6.png index 80bf28136..a8f0ab9c0 100644 Binary files a/APP_Framework/Applications/app_test/test_radix_tree/fig6.png and b/APP_Framework/Applications/app_test/test_radix_tree/fig6.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/fig7.png b/APP_Framework/Applications/app_test/test_radix_tree/fig7.png index 7fad83c9e..4b1073ba4 100644 Binary files a/APP_Framework/Applications/app_test/test_radix_tree/fig7.png and b/APP_Framework/Applications/app_test/test_radix_tree/fig7.png differ diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c index c54a49805..a2c96e15e 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.c @@ -1,23 +1,27 @@ /** -* @file: test_radix_tree.c -* @brief: Implement a simple radix tree -* @version: 1.0 -* @date: 2023/5/24 -*/ + * @file: test_radix_tree.c + * @brief: Implement a simple radix tree + * @version: 1.0 + * @date: 2023/5/24 + */ -#include #include "test_radix_tree.h" /** * @description: Create a radix tree node * @return node pointer */ -node* CreateNode() +radix_node *CreateNode() { - node* n = (node*)malloc(sizeof(node)); - n->value = NULL; - for (int i = 0; i < NODE_SIZE; i++) { - n->next[i] = NULL; + radix_node *n = (radix_node *)malloc(sizeof(radix_node)); + if (n != NULL) + { + n->parent = NULL; + n->value = NULL; + for (int i = 0; i < NODE_SIZE; ++i) + { + n->child[i] = NULL; + } } return n; } @@ -29,21 +33,32 @@ node* CreateNode() * @param value - new node value * @return void */ -void InsertNode(node* root, const char* key, void* value) +int InsertNode(radix_node *root, unsigned int key, void *value) { - if (root == NULL) { - return; + if (root == NULL) + { + return -1; // The root node is empty } - node* cur = root; - size_t len = strlen(key); - for (size_t i = 0; i < len; i++) { - uint8_t b = (uint8_t)key[i]; - if (cur->next[b] == NULL) { - cur->next[b] = CreateNode(); + radix_node *cur = root; + int temp; + for (int i = radix_tree_height - 1; i >= 0; --i) + { + temp = CHECK_BITS(key, i); + if (!cur->child[temp]) + { + cur->child[temp] = CreateNode(); + if (!cur->child[temp]) + return -2; // Failed to apply for a node + cur->child[temp]->parent = cur; } - cur = cur->next[b]; + cur = cur->child[temp]; } + if (cur->value == value) + return -3; // Repeat insertion + if (cur->value != NULL) + return -4; // Already occupied cur->value = value; + return 0; } /** @@ -52,38 +67,27 @@ void InsertNode(node* root, const char* key, void* value) * @param key - key which is needed to delete * @return void */ -void DeleteNode(node* root, const char* key) +void DeleteNode(radix_node *root, unsigned int key) { - if (root == NULL) { + if (root == NULL) + { return; } - node** cur = &root; - size_t len = strlen(key); - for (size_t i = 0; i < len; i++) { - uint8_t b = (uint8_t)key[i]; - if ((*cur)->next[b] == NULL) { - return; - } - cur = &((*cur)->next[b]); - } - - if ((*cur)->value == NULL) { - return; - } - - (*cur)->value = NULL; - - int has_children = 0; - for (int i = 0; i < NODE_SIZE; i++) { - if ((*cur)->next[i] != NULL) { - has_children = 1; + radix_node *cur = root; + int temp; + for (int i = radix_tree_height - 1; i >= 0; --i) + { + temp = CHECK_BITS(key, i); + cur = cur->child[temp]; + if (!cur) break; - } - } - if (!has_children) { - free(*cur); - (*cur) = NULL; } + + if (!cur) + return; + + cur->parent->child[temp] = NULL; + free(cur); } /** @@ -92,20 +96,23 @@ void DeleteNode(node* root, const char* key) * @param key - key which is needed to find * @return value pointer corresponding to key */ -void* FindNode(node* root, const char* key) +void *FindNode(radix_node *root, unsigned int key) { - if (root == NULL) { + if (root == NULL) + { return NULL; } - node* cur = root; - size_t len = strlen(key); - for (size_t i = 0; i < len; i++) { - uint8_t b = (uint8_t)key[i]; - if (cur->next[b] == NULL) { - return NULL; - } - cur = cur->next[b]; + radix_node *cur = root; + int temp; + for (int i = radix_tree_height - 1; i >= 0; --i) + { + temp = CHECK_BITS(key, i); + cur = cur->child[temp]; + if (!cur) + break; } + if (!cur) + return NULL; return cur->value; } @@ -114,73 +121,88 @@ void* FindNode(node* root, const char* key) * @param root - radix tree root * @return void */ -void DestroyTree(node* root) +void DestroyTree(radix_node *root) { - if (root == NULL) { + if (root == NULL) + { return; } - for (int i = 0; i < NODE_SIZE; i++) { - DestroyTree(root->next[i]); + for (int i = 0; i < NODE_SIZE; i++) + { + DestroyTree(root->child[i]); } free(root); } void TestRadix() { - char keys[][MAX_WORD_LEN] = { + char values[][16] = { "what", "where", "why", "how", "hello!", "apple", - "12345" - }; - int values[] = {1, 2, 3, 4, 5, 6, 7}; + "12345"}; + unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7}; printf("\nCreate tree and add key & value:\n"); - node* root = CreateNode(); - if (!root) printf("Create node failed.\n"); + radix_node *root = CreateNode(); + if (!root) + printf("Create node failed.\n"); int num = sizeof(keys) / sizeof(keys[0]); - for (int i = 0; i < num - 1; ++i) { + for (int i = 0; i < num - 1; ++i) + { InsertNode(root, keys[i], &values[i]); } - for (int i = 0; i < num; ++i) { - int* v = (int*)FindNode(root, keys[i]); - if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]); - else printf("keys[%d] \"%s\" not found\n", i, keys[i]); + for (int i = 0; i < num; ++i) + { + char *v = (char *)FindNode(root, keys[i]); + if (v) + printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v); + else + printf("keys[%d] %x not found\n", i, keys[i]); } printf("\nDelete \"where\" and \"how\":\n"); DeleteNode(root, keys[1]); DeleteNode(root, keys[3]); - - for (int i = 0; i < num; ++i) { - int* v = (int*)FindNode(root, keys[i]); - if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]); - else printf("keys[%d] \"%s\" not found\n", i, keys[i]); + + for (int i = 0; i < num; ++i) + { + char *v = (char *)FindNode(root, keys[i]); + if (v) + printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v); + else + printf("keys[%d] %x not found\n", i, keys[i]); } printf("\nInsert \"where\" and \"12345\":\n"); InsertNode(root, keys[1], &values[1]); InsertNode(root, keys[6], &values[6]); - for (int i = 0; i < num; ++i) { - int* v = (int*)FindNode(root, keys[i]); - if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]); - else printf("keys[%d] \"%s\" not found\n", i, keys[i]); + for (int i = 0; i < num; ++i) + { + char *v = (char *)FindNode(root, keys[i]); + if (v) + printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v); + else + printf("keys[%d] %x not found\n", i, keys[i]); } printf("\nDestroy tree:\n"); DestroyTree(root); root = NULL; - for (int i = 0; i < num; ++i) { - int* v = (int*)FindNode(root, keys[i]); - if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]); - else printf("keys[%d] \"%s\" not found\n", i, keys[i]); + for (int i = 0; i < num; ++i) + { + char *v = (char *)FindNode(root, keys[i]); + if (v) + printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v); + else + printf("keys[%d] %x not found\n", i, keys[i]); } } diff --git a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h index ea9e7b7fa..cef53561f 100644 --- a/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h +++ b/APP_Framework/Applications/app_test/test_radix_tree/test_radix_tree.h @@ -1,20 +1,27 @@ /** -* @file: test_radix_tree.h -* @brief: Implement a simple radix tree -* @version: 1.0 -* @date: 2023/5/24 -*/ + * @file: test_radix_tree.h + * @brief: Implement a simple radix tree + * @version: 1.0 + * @date: 2023/5/24 + */ -#define NODE_SIZE 128 -#define MAX_WORD_LEN 128 +#include -typedef struct _node { - void* value; - struct _node* next[NODE_SIZE]; -} node; +#define NODE_SIZE 4 +#define BITS 2 +#define CHECK_BITS(key, pos) ((((unsigned int)(key)) << (sizeof(int) * 8 - (pos + 1) * BITS)) >> (sizeof(int) * 8 - BITS)) -node* CreateNode(); -void InsertNode(node* root, const char* key, void* value); -void DeleteNode(node* root, const char* key); -void* FindNode(node* root, const char* key); -void DestroyTree(node* root); \ No newline at end of file +const int radix_tree_height = sizeof(void *) * 8 / BITS; // Height of tree + +typedef struct radix_node +{ + void *value; + struct radix_node *child[NODE_SIZE]; + struct radix_node *parent; +} radix_node; + +radix_node *CreateNode(); +int InsertNode(radix_node *root, unsigned int key, void *value); +void DeleteNode(radix_node *root, unsigned int key); +void *FindNode(radix_node *root, unsigned int key); +void DestroyTree(radix_node *root); \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_rs485.c b/APP_Framework/Applications/app_test/test_rs485.c index bbe6f1c4d..0b562359c 100644 --- a/APP_Framework/Applications/app_test/test_rs485.c +++ b/APP_Framework/Applications/app_test/test_rs485.c @@ -22,26 +22,94 @@ #include #ifdef ADD_XIZI_FEATURES -#define BSP_485_DIR_PIN 24 +//edu-arm board dir pin PG01----no.67 in XiZi_IIoT/board/edu_arm32/third_party_driver/gpio/connect_gpio.c +#define BSP_485_DIR_PIN 67 + +static int pin_fd; +static int uart_fd; +static char write_485_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; +static char read_485_data[8] = {0}; + +/** + * @description: Set Uart 485 Input + * @return + */ +static void Set485Input(void) +{ + struct PinStat pin_stat; + pin_stat.pin = BSP_485_DIR_PIN; + pin_stat.val = GPIO_LOW; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Set Uart 485 Output + * @return + */ +static void Set485Output(void) +{ + struct PinStat pin_stat; + pin_stat.pin = BSP_485_DIR_PIN; + pin_stat.val = GPIO_HIGH; + PrivWrite(pin_fd, &pin_stat, 1); +} + +/** + * @description: Control Framework Serial Write + * @param write_data - write data + * @param length - length + * @return + */ +void Rs485Write(uint8_t *write_data, int length) +{ + Set485Output(); + PrivTaskDelay(20); + + PrivWrite(uart_fd, write_data, length); + + PrivTaskDelay(15); + Set485Input(); +} + +/** + * @description: Control Framework Serial Read + * @param read_data - read data + * @param length - length + * @return read data size + */ +int Rs485Read(uint8_t *read_data, int length) +{ + int data_size = 0; + int data_recv_size = 0; + + while (data_size < length) { + data_recv_size = PrivRead(uart_fd, read_data + data_size, length - data_size); + data_size += data_recv_size; + } + + //need to wait 30ms , make sure write cmd again and receive data successfully + PrivTaskDelay(30); + + return data_size; +} void Test485(void) { - int pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR); - if (pin_fd < 0) - { + int read_data_length = 0; + pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR); + if (pin_fd < 0) { printf("open pin fd error:%d\n", pin_fd); return; } - int uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR); - if (uart_fd < 0) - { + uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR); + if (uart_fd < 0) { printf("open pin fd error:%d\n", uart_fd); return; } printf("uart and pin fopen success\n"); - //config led pin in board + //config dir pin in board struct PinParam pin_parameter; memset(&pin_parameter, 0, sizeof(struct PinParam)); pin_parameter.cmd = GPIO_CONFIG_MODE; @@ -68,36 +136,34 @@ void Test485(void) uart_cfg.serial_bit_order = BIT_ORDER_LSB; uart_cfg.serial_invert_mode = NRZ_NORMAL; uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; - uart_cfg.serial_timeout = 1000; + uart_cfg.serial_timeout = -1; uart_cfg.is_ext_uart = 0; ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; ioctl_cfg.args = (void *)&uart_cfg; - if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg)) - { + if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg)) { printf("ioctl uart fd error %d\n", uart_fd); PrivClose(uart_fd); return; } - struct PinStat pin_dir; - pin_dir.pin = BSP_485_DIR_PIN; - while (1) - { - pin_dir.val = GPIO_HIGH; - PrivWrite(pin_fd,&pin_dir,0); - PrivWrite(uart_fd,"Hello world!\n",sizeof("Hello world!\n")); - PrivTaskDelay(100); + Rs485Write(write_485_data, sizeof(write_485_data)); - pin_dir.val = GPIO_LOW; - PrivWrite(pin_fd,&pin_dir,0); - char recv_buff[100]; - memset(recv_buff,0,sizeof(recv_buff)); - PrivRead(uart_fd,recv_buff,20); - printf("%s",recv_buff); - PrivTaskDelay(100); + while(1) { + printf("ready to read data\n"); + + read_data_length = Rs485Read(read_485_data, sizeof(read_485_data)); + printf("%s read data length %d\n", __func__, read_data_length); + for (int i = 0; i < read_data_length; i ++) { + printf("i %d read data 0x%x\n", i, read_485_data[i]); + } + Rs485Write(read_485_data, read_data_length); + memset(read_485_data, 0, sizeof(read_485_data)); + + printf("read data done\n"); } + PrivClose(pin_fd); PrivClose(uart_fd); return; diff --git a/APP_Framework/Applications/app_test/test_socket.c b/APP_Framework/Applications/app_test/test_socket.c new file mode 100644 index 000000000..81c4543cc --- /dev/null +++ b/APP_Framework/Applications/app_test/test_socket.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2020 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. + */ + +#include +#include +#include + +#include "lwip/sockets.h" +#include "sys_arch.h" + +#define IPERF_PORT 5001 +#define IPERF_BUFSZ (4 * 1024) + +enum IperfMode { + IPERF_MODE_STOP = (1 << 0), + IPERF_MODE_SERVER = (1 << 1), + IPERF_MODE_CLIENT = (1 << 2), +}; + +struct AtomicIperfMode { + /* pthread_mutex_t here is a int */ + pthread_mutex_t mtx; + enum IperfMode mode; +}; + +static struct AtomicIperfMode* GetGlobalIperfMode() +{ + /* init when used */ + static struct AtomicIperfMode g_iperf_mode = { + -1, + IPERF_MODE_STOP, + }; + if (g_iperf_mode.mtx < 0) { + /* mtx is a static obj, so there is only creation but not destruction */ + PrivMutexCreate(&g_iperf_mode.mtx, NULL); + /* init lwip if necessary */ + lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); + } + return &g_iperf_mode; +} + +static enum IperfMode GetGlobalMode() +{ + enum IperfMode mode = IPERF_MODE_STOP; + struct AtomicIperfMode* g_mode = GetGlobalIperfMode(); + + PrivMutexObtain(&g_mode->mtx); + mode = g_mode->mode; + PrivMutexAbandon(&g_mode->mtx); + + return mode; +} + +static void SetGlobalMode(enum IperfMode mode) +{ + struct AtomicIperfMode* g_mode = GetGlobalIperfMode(); + PrivMutexObtain(&g_mode->mtx); + g_mode->mode = mode; + PrivMutexAbandon(&g_mode->mtx); +} + +struct IperfParam { + char host[16]; + int port; +}; + +static void* TestIperfServer(void* param) +{ + struct IperfParam* iperf_param = (struct IperfParam*)param; + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + printf("[%s] Err: Can't create socker.\n", __func__); + return NULL; + } + + uint8_t* recv_data = (uint8_t*)malloc(IPERF_BUFSZ); + if (recv_data == NULL) { + KPrintf("[%s] No memory to alloc buffer!\n", __func__); + goto __exit; + } + + struct sockaddr_in server_addr, client_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(iperf_param->port); + server_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); + + if (bind(sock, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) == -1) { + KPrintf("[%s] Err: Unable to bind socket: %d!\n", __func__, sock); + goto __exit; + } + + if (listen(sock, 5) == -1) { + KPrintf("[%s] Err: Listen error!\n", __func__); + goto __exit; + } + + struct timeval timeout = { + .tv_sec = 3, + .tv_usec = 0, + }; + + fd_set readset; + while (GetGlobalMode() == IPERF_MODE_SERVER) { + FD_ZERO(&readset); + FD_SET(sock, &readset); + + if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0) { + continue; + } + + socklen_t sin_size = sizeof(struct sockaddr_in); + struct sockaddr_in client_addr; + int connection = accept(sock, (struct sockaddr*)&client_addr, &sin_size); + printf("[%s] Info: New client connected from (%s, %d)\n", __func__, + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + + int flag = 1; + setsockopt(connection, + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (void*)&flag, /* the cast is historical cruft */ + sizeof(int)); /* length of option value */ + + int recvlen = 0; + int tick_beg = PrivGetTickTime(); + int tick_end = tick_beg; + while (GetGlobalMode() == IPERF_MODE_SERVER) { + int bytes_received = recv(connection, recv_data, IPERF_BUFSZ, 0); + if (bytes_received == 0) { + KPrintf("client disconnected (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } else if (bytes_received < 0) { + KPrintf("recv error, client: (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } + + recvlen += bytes_received; + + tick_end = PrivGetTickTime(); + if (tick_end - tick_beg >= 5000) { + double speed; + // int integer, decimal; + + speed = (double)(recvlen / (tick_end - tick_beg)); + speed = speed / 1000.0f; + printf("[%s]: %2.4f MBps!\n", __func__, speed); + tick_beg = tick_end; + recvlen = 0; + } + } + if (connection >= 0) + closesocket(connection); + connection = -1; + } + +__exit: + if (sock >= 0) + closesocket(sock); + if (recv_data) + free(recv_data); + return NULL; +} + +static void* TestIperfClient(void* param) +{ + struct IperfParam* iperf_param = (struct IperfParam*)param; + + uint8_t* send_buf + = (uint8_t*)malloc(IPERF_BUFSZ); + if (NONE == send_buf) { + printf("[%s] Err: Unable to alloc buffer\n", __func__); + return NULL; + } + for (int i = 0; i < IPERF_BUFSZ; i++) { + send_buf[i] = i & 0xff; + } + + struct sockaddr_in addr; + while (GetGlobalMode() == IPERF_MODE_CLIENT) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + printf("[%s] Warning: Can't create socker.\n", __func__); + PrivTaskDelay(1000); + continue; + } + + addr.sin_family = PF_INET; + addr.sin_port = htons(iperf_param->port); + addr.sin_addr.s_addr = inet_addr((char*)iperf_param->host); + + int ret = connect(sock, (const struct sockaddr*)&addr, sizeof(addr)); + if (ret == -1) { + printf("[%s] Warning: Connect to iperf server faile, Waiting for the server to open!\n", __func__); + closesocket(sock); + DelayKTask(TICK_PER_SECOND); + continue; + } + printf("[%s] Connect to iperf server successful!\n", __func__); + + int flag = 1; + setsockopt(sock, + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (void*)&flag, /* the cast is historical cruft */ + sizeof(int)); /* length of option value */ + + int tick_beg = PrivGetTickTime(); + int tick_end = tick_beg; + int sentlen = 0; + while (GetGlobalMode() == IPERF_MODE_CLIENT) { + tick_end = PrivGetTickTime(); + /* Print every 5 second */ + if (tick_end - tick_beg >= 5000) { + double speed; + + speed = (double)(sentlen / (tick_end - tick_beg)); + speed = speed / 1000.0f; + printf("[%s]: %2.4f MBps!\n", __func__, speed); + tick_beg = tick_end; + sentlen = 0; + } + + ret = send(sock, send_buf, IPERF_BUFSZ, 0); + if (ret > 0) { + sentlen += ret; + } + + if (ret < 0) + break; + } + + closesocket(sock); + printf("[%s] Info: Disconnected, iperf server shut down!\n", __func__); + } + free(send_buf); + return NULL; +} + +enum IperfParamEnum { + IPERF_PARAM_SERVER = 's', + IPERF_PARAM_CLIENT = 'c', + IPERF_PARAM_STOP = 0, + IPERF_PARAM_IPADDR = 0, + IPERF_PARAM_PORT = 'p', +}; + +void TestSocket(int argc, char* argv[]) +{ + lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); + + static char usage_info[] = "Run either a iperf server or iperf client."; + static char program_info[] = "Lwip socket test task, a simple iperf."; + static const char* const usages[] = { + "TestIperf -c [--ip arg] [-p arg]", + "TestIperf -s [-p arg]", + NULL, + }; + + static struct IperfParam iperf_param = { + .host = "255.255.255.255", + .port = 5001, + }; + + enum IperfMode mode = 0; + char* ip_ptr = NULL; + bool is_help = false; + struct argparse_option options[] = { + OPT_HELP(&is_help), + OPT_GROUP("Bit Options"), + OPT_BIT(IPERF_PARAM_SERVER, "server", &mode, "start a iperf server", NULL, IPERF_MODE_SERVER, 0), + OPT_BIT(IPERF_PARAM_CLIENT, "client", &mode, "start a iperf client", NULL, IPERF_MODE_CLIENT, 0), + OPT_BIT(IPERF_PARAM_STOP, "stop", &mode, "stop iperf", NULL, IPERF_MODE_STOP, OPT_NONEG), + OPT_GROUP("Param Options"), + OPT_STRING(IPERF_PARAM_IPADDR, "ip", &ip_ptr, "server IP if iperf is a client", NULL, 0, 0), + OPT_INTEGER(IPERF_PARAM_PORT, "port", &iperf_param.port, "server PORT needed for iperf", NULL, 0, 0), + OPT_END(), + }; + + struct argparse argparse; + argparse_init(&argparse, options, usages, 0); + argparse_describe(&argparse, usage_info, program_info); + argc = argparse_parse(&argparse, argc, (const char**)argv); + /* help task */ + if (is_help) { + return; + } + + /* stop iperf task */ + if (mode & IPERF_MODE_STOP) { + SetGlobalMode(IPERF_MODE_STOP); + return; + } + if (mode & IPERF_MODE_SERVER && mode & IPERF_MODE_CLIENT) { + printf("[%s] Err: Can't run iperf server and client at one time.\n", __func__); + } + + /* iperf server or iperf client*/ + struct AtomicIperfMode* iperf_mode = GetGlobalIperfMode(); + PrivMutexObtain(&iperf_mode->mtx); + if (iperf_mode->mode != IPERF_MODE_STOP) { + PrivMutexAbandon(&iperf_mode->mtx); + printf("[%s] Err: There is already a iperf running, please stop it before running a new one\n", __func__); + return; + } + + if (mode & IPERF_MODE_SERVER) { + iperf_mode->mode = IPERF_MODE_SERVER; + } else if (mode & IPERF_MODE_CLIENT) { + if (ip_ptr == NONE) { + PrivMutexAbandon(&iperf_mode->mtx); + printf("[%s] Err: Iperf client must assign a server ip.\n", __func__); + return; + } else { + memset(iperf_param.host, 0, sizeof(iperf_param.host)); + strncpy(iperf_param.host, ip_ptr, strlen(ip_ptr)); + } + iperf_mode->mode = IPERF_MODE_CLIENT; + } + PrivMutexAbandon(&iperf_mode->mtx); + + pthread_t thd; + mode = GetGlobalMode(); + if (mode == IPERF_MODE_SERVER) { + printf("[%s] Running iperf server at port %d.\n", __func__, iperf_param.port); + + PrivTaskCreate(&thd, NULL, TestIperfServer, (void*)&iperf_param); + } else if (mode == IPERF_MODE_CLIENT) { + printf("[%s] Running iperf client to server at %s:%d.\n", __func__, iperf_param.host, iperf_param.port); + PrivTaskCreate(&thd, NULL, TestIperfClient, (void*)&iperf_param); + } + + PrivTaskStartup(&thd); +} + +PRIV_SHELL_CMD_FUNCTION(TestSocket, Test socket using iperf, PRIV_SHELL_CMD_MAIN_ATTR | SHELL_CMD_PARAM_NUM(8)); \ No newline at end of file diff --git a/APP_Framework/Applications/app_test/test_uart.c b/APP_Framework/Applications/app_test/test_uart.c new file mode 100644 index 000000000..c714269ab --- /dev/null +++ b/APP_Framework/Applications/app_test/test_uart.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2020 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: test_uart.c + * @brief: a application of uart function, uart6 for edu-arm32 + * @version: 3.0 + * @author: AIIT XUOS Lab + * @date: 2023/8/11 + */ +#include +#include +#include + +#include + +#include +#ifdef ADD_XIZI_FEATURES + +void TestUart(int argc, char* argv[]) +{ + static char program_info[] = "App Test uart, sending a message through uart and receive messages from uart."; + static const char* const usages[] = { + "TestUart -m arg", + NULL, + }; + + bool is_help = false; + char* msg = NULL; + struct argparse_option options[] = { + OPT_HELP(&is_help), + OPT_STRING('m', "message", &msg, "MESSAGE to send through uart.", NULL, 0, 0), + OPT_END(), + }; + struct argparse argparse; + argparse_init(&argparse, options, usages, 0); + argparse_describe(&argparse, NULL, program_info); + argc = argparse_parse(&argparse, argc, (const char**)argv); + if (is_help) { + return; + } + + int uart_fd = PrivOpen(UART_DEV_DRIVER, O_RDWR); + if (uart_fd < 0) { + printf("open pin fd error:%d\n", uart_fd); + return; + } + printf("[%s] Info: Uart and pin fopen success\n", __func__); + + struct SerialDataCfg uart_cfg; + memset(&uart_cfg, 0, sizeof(struct SerialDataCfg)); + + uart_cfg.serial_baud_rate = BAUD_RATE_115200; + uart_cfg.serial_data_bits = DATA_BITS_8; + uart_cfg.serial_stop_bits = STOP_BITS_1; + uart_cfg.serial_parity_mode = PARITY_NONE; + uart_cfg.serial_bit_order = BIT_ORDER_LSB; + uart_cfg.serial_invert_mode = NRZ_NORMAL; + uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ; + uart_cfg.serial_timeout = -1; + uart_cfg.is_ext_uart = 0; + + struct PrivIoctlCfg ioctl_cfg; + ioctl_cfg.ioctl_driver_type = SERIAL_TYPE; + ioctl_cfg.args = (void*)&uart_cfg; + + if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg)) { + printf("[%s] Err: ioctl uart fd error %d\n", __func__, uart_fd); + PrivClose(uart_fd); + return; + } + PrivWrite(uart_fd, msg, strlen(msg)); + + char recv_buf[100]; + while (1) { + memset(recv_buf, 0, sizeof(recv_buf)); + PrivRead(uart_fd, recv_buf, sizeof(recv_buf)); + printf("[%s] Info: Recv from uart: %s\n", __func__, recv_buf); + } + + PrivClose(uart_fd); + return; +} + +PRIV_SHELL_CMD_FUNCTION(TestUart, a uart test sample, PRIV_SHELL_CMD_MAIN_ATTR); +#endif \ No newline at end of file diff --git a/APP_Framework/Applications/main.c b/APP_Framework/Applications/main.c index e1de024b5..b10557a97 100644 --- a/APP_Framework/Applications/main.c +++ b/APP_Framework/Applications/main.c @@ -15,7 +15,6 @@ // #include #include - extern int FrameworkInit(); extern void ApplicationOtaTaskInit(void); int main(void) diff --git a/APP_Framework/Applications/webnet/Makefile b/APP_Framework/Applications/webnet/Makefile new file mode 100644 index 000000000..8eca9e823 --- /dev/null +++ b/APP_Framework/Applications/webnet/Makefile @@ -0,0 +1,3 @@ +SRC_DIR += WebNet_XiUOS + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/APP_Framework/Applications/webnet/WebNet_XiUOS b/APP_Framework/Applications/webnet/WebNet_XiUOS index 956eafa24..60a8a500b 160000 --- a/APP_Framework/Applications/webnet/WebNet_XiUOS +++ b/APP_Framework/Applications/webnet/WebNet_XiUOS @@ -1 +1 @@ -Subproject commit 956eafa24bb65f5bb84d293ab35bf27084473edf +Subproject commit 60a8a500b93b47876c6eaff600e4cf2b8bf7b283 diff --git a/APP_Framework/Framework/control/shared/control_io.c b/APP_Framework/Framework/control/shared/control_io.c index fbb01b7ec..5d9e00060 100644 --- a/APP_Framework/Framework/control/shared/control_io.c +++ b/APP_Framework/Framework/control/shared/control_io.c @@ -180,7 +180,7 @@ int SerialRead(uint8_t *read_data, int length) int data_recv_size = 0; while (data_size < length) { - data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length); + data_recv_size = PrivRead(uart_fd, read_data + data_size, length - data_size); data_size += data_recv_size; } diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.c b/APP_Framework/Framework/transform_layer/xizi/transform.c index 002c8f1be..ba0b8f614 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.c +++ b/APP_Framework/Framework/transform_layer/xizi/transform.c @@ -164,7 +164,7 @@ int PrivTimerModify(timer_t timerid, int flags, const struct itimerspec *restric /*********************fs**************************/ #ifdef FS_VFS /************************Driver Posix Transform***********************/ -int PrivOpen(const char *path, int flags) +int PrivOpen(const char *path, int flags, ...) { return open(path, flags); } diff --git a/APP_Framework/Framework/transform_layer/xizi/transform.h b/APP_Framework/Framework/transform_layer/xizi/transform.h index fe817f18a..ef1894c32 100644 --- a/APP_Framework/Framework/transform_layer/xizi/transform.h +++ b/APP_Framework/Framework/transform_layer/xizi/transform.h @@ -427,7 +427,7 @@ uint32_t PrivGetTickTime(); /*********************driver*************************/ -int PrivOpen(const char *path, int flags); +int PrivOpen(const char *path, int flags, ...); int PrivRead(int fd, void *buf, size_t len); int PrivWrite(int fd, const void *buf, size_t len); int PrivClose(int fd); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/mqueue.h b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/mqueue.h index ae13f6667..6ac021b36 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/mqueue.h +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/include/mqueue.h @@ -40,7 +40,8 @@ struct mq_attr { long mq_curmsgs; /* number of messages currently queued */ }; -mqd_t mq_open(const char *name, int oflag, ...); +// mqd_t mq_open(const char *name, int oflag, ...); +mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr); int mq_close(mqd_t mqdes); ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); diff --git a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/mqueue.c b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/mqueue.c index e0f5e9507..9f13a1445 100644 --- a/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/mqueue.c +++ b/APP_Framework/Framework/transform_layer/xizi/user_api/posix_support/mqueue.c @@ -21,12 +21,13 @@ #include "include/mqueue.h" -mqd_t mq_open(const char *name, int oflag, ...) +mqd_t mq_open(const char* name, int oflag, mode_t mode, struct mq_attr* attr) { mqd_t mq; - mq = UserMsgQueueCreate( DEFAULT_MQUEUE_SIZE, DEFAULT_MAX_MSG_SIZE); + // Todo: config mq by mode + mq = UserMsgQueueCreate(attr->mq_msgsize, attr->mq_maxmsg); if (mq < 0) { return -1; } @@ -39,12 +40,12 @@ int mq_close(mqd_t mqdes) return UserMsgQueueDelete(mqdes); } -ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio) +ssize_t mq_receive(mqd_t mqdes, char* msg_ptr, size_t msg_len, unsigned* msg_prio) { ssize_t ret; *msg_prio = 0; - ret = UserMsgQueueRecv(mqdes, msg_ptr, (unsigned long)&msg_len, 0); + ret = UserMsgQueueRecv(mqdes, (void*)msg_ptr, msg_len, WAITING_FOREVER); return ret; } diff --git a/APP_Framework/lib/lorawan/lora_radio_driver b/APP_Framework/lib/lorawan/lora_radio_driver index d21965b1c..a94c007cb 160000 --- a/APP_Framework/lib/lorawan/lora_radio_driver +++ b/APP_Framework/lib/lorawan/lora_radio_driver @@ -1 +1 @@ -Subproject commit d21965b1cbcfa99b2d36acd029a37f3f2eba612e +Subproject commit a94c007cb4ee726cc29b10626f8bbfc19c989b89 diff --git a/APP_Framework/lib/lorawan/lorawan_devicenode b/APP_Framework/lib/lorawan/lorawan_devicenode index 2896d7234..254754bc7 160000 --- a/APP_Framework/lib/lorawan/lorawan_devicenode +++ b/APP_Framework/lib/lorawan/lorawan_devicenode @@ -1 +1 @@ -Subproject commit 2896d7234688de77992e7e1872a7e67a9456b420 +Subproject commit 254754bc7d06011cbec4655cd229c8ccfb95240b diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile index 262587f99..c794367b8 100644 --- a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := cache.c isr.c mmu.c +SRC_FILES := cache.c isr.c abstraction_mmu.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.c new file mode 100755 index 000000000..6f37b7d6f --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.c @@ -0,0 +1,206 @@ +/* +* Copyright (c) 2020 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: abstraction_mmu.c +* @brief: the general management of system mmu +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/4/27 +* +*/ + +#include + +AbstractionMmu abstraction_mmu; + +volatile uint32_t global_L1_pte_table[4096]; + +/** + * @description: write cmd to CP15 register + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuCp15Write(uint8_t reg_type, uint32_t *val) +{ + uint32_t write_val = *val; + switch (reg_type) { + case AM_MMU_CP15_TTBCR: + TTBCR_W(write_val); + AM_ISB; + case AM_MMU_CP15_TTBR0: + TTBR0_W(write_val); + AM_ISB; + default: + break; + } +} + +/** + * @description: read CP15 register from mmu + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuCp15Read(uint8_t reg_type, uint32_t *val) +{ + uint32_t read_val = 0; + switch (reg_type) { + case AM_MMU_CP15_TTBCR: + TTBCR_R(read_val); + case AM_MMU_CP15_TTBR0: + TTBR0_R(read_val); + default: + break; + } + + *val = read_val; +} + +/** + * @description: write or read CP15 register to set mmu + * @param ops_type - CP15 write or read + * @param reg_type - CP15 register type + * @param val - ops val pointer + * @return + */ +static void MmuRegOps(uint8_t ops_type, uint8_t reg_type, uint32_t *val) +{ + switch (ops_type) { + case AM_MMU_CP15_WRITE: + MmuCp15Write(reg_type, val); + case AM_MMU_CP15_READ: + MmuCp15Read(reg_type, val); + default: + break; + } +} + +/** + * @description: Init abstraction_mmu function + * @param mmu - abstraction mmu pointer + * @param ttb_base - ttb base pointer + * @return success : 0 error : -1 + */ +static int _AbstractionMmuInit(AbstractionMmu *mmu, uint32_t *ttb_base) +{ + mmu_init(); + + return 0; +} + +/** + * @description: map L1 or L2 page table section + * @param mmu - abstraction mmu pointer + * @param section_size - section size + * @return success : 0 error : -1 + */ +static int _AbstractionMmuSectionMap(AbstractionMmu *mmu, uint32_t section_size) +{ + uint32_t vaddr_length = mmu->vaddr_end - mmu->vaddr_start + 1; + + mmu_map_l1_range(mmu->paddr_start, mmu->vaddr_start, vaddr_length, + mmu->mmu_memory_type, mmu->mmu_shareability, mmu->mmu_access); + + mmu->mmu_status = 1; + + return 0; +} + +/** + * @description: unmap L1 or L2 page table section + * @param mmu - abstraction mmu pointer + * @param vaddr_start - virtual address start + * @param vaddr_size - virtual address size + * @return success : 0 error : -1 + */ +static int _AbstractionMmuSectionUnmap(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size) +{ + uint32_t *l1_umap_ventry = mmu->ttb_vbase + (vaddr_start >> AM_MMU_L1_SECTION_SHIFT); + uint32_t vaddr_end = vaddr_start + vaddr_size - 1; + uint32_t umap_count = (vaddr_end >> AM_MMU_L1_SECTION_SHIFT) - (vaddr_start >> AM_MMU_L1_SECTION_SHIFT) + 1; + + while (umap_count) { + AM_DMB; + *l1_umap_ventry = 0; + AM_DSB; + + umap_count--; + l1_umap_ventry += (1 << AM_MMU_L1_SECTION_SHIFT);//1MB section + } + + AM_DSB; + CLEARTLB(0);//clear TLB data and configure + AM_DSB; + AM_ISB; + mmu->mmu_status = 0; + + return 0; +} + +/** + * @description: switch ttb base by re-write ttbr register + * @param mmu - abstraction mmu pointer + * @return success : 0 error : -1 + */ +static int _AbstractionMmuTtbSwitch(AbstractionMmu *mmu) +{ + uint32_t ttbr, ttbcr; + MmuRegOps(AM_MMU_CP15_READ, AM_MMU_CP15_TTBCR, &ttbcr); + + /* Set TTBR0 with inner/outer write back write allocate and not shareable, [4:3]=01, [1]=0, [6,0]=01 */ + ttbr = ((mmu->ttb_pbase & 0xFFFFC000UL) | 0x9UL); + /* enable TTBR0 */ + ttbcr = 0; + + AM_DSB; + MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBR0, &ttbr); + MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBCR, &ttbcr); + + return 0; +} + +/** + * @description: get physical address transformed from virtual address + * @param mmu - abstraction mmu pointer + * @param vaddr - virtual address pointer + * @param paddr - physical address pointer + * @return success : 0 error : -1 + */ +static int _AbstracktonMmuTransform(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr) +{ + uint32_t virtualAddress = *vaddr; + + if (mmu->mmu_status) { + mmu_virtual_to_physical(virtualAddress, paddr); + } + + return 0; +} + +static struct AbstractionMmuDone mmu_done = { + .AbstractionMmuInit = _AbstractionMmuInit, + .AbstractionMmuSectionMap = _AbstractionMmuSectionMap, + .AbstractionMmuSectionUnmap = _AbstractionMmuSectionUnmap, + .AbstractionMmuTtbSwitch = _AbstractionMmuTtbSwitch, + .AbstracktonMmuTransform = _AbstracktonMmuTransform, +}; + +/** + * @description: init abstraciton mmu info when system start + * @return success : 0 error : -1 + */ +int SysInitAbstractionMmu(void) +{ + abstraction_mmu.mmu_done = &mmu_done; +} diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.h b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.h new file mode 100644 index 000000000..ce3c35d06 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/abstraction_mmu.h @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2020 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: mmu.h +* @brief: the general management of system mmu +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/5/24 +* +*/ +#include +#include + +#define ARCH_ARM +#ifdef ARCH_ARM +/* ARM System Registers */ +#define AM_DSB __asm__ volatile("dsb" ::: "memory") +#define AM_DMB __asm__ volatile("dmb" ::: "memory") +#define AM_ISB __asm__ volatile("isb" ::: "memory") +#define AM_WFI __asm__ volatile("wfi" ::: "memory") +#define AM_BARRIER __asm__ volatile("":::"memory") +#define AM_WFE __asm__ volatile("wfe" ::: "memory") +#define AM_SEV __asm__ volatile("sev" ::: "memory") + +#define TTBR0_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(val)) +#define TTBR0_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" ::"r"(val)) + +#define TTBCR_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(val)) +#define TTBCR_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" ::"r"(val)) + +#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val)) +#endif + +#define AM_MMU_L1_PAGE_TABLE_SIZE (4 * 4096) +#define AM_MMU_L1_SECTION_SHIFT 20 + +typedef enum +{ + AM_MMU_CP15_WRITE = 0, + AM_MMU_CP15_READ, +}MmuCP15OpsType; + +typedef enum +{ + AM_MMU_CP15_TTBCR = 0, + AM_MMU_CP15_TTBR0, + AM_MMU_CP15_CLEARTLB, +}MmuCP15RegType; + +typedef enum +{ + AM_StronglyOrdered = 0, + AM_Device, + AM_OuterInner_WB_WA, + AM_OuterInner_WT, + AM_Noncacheable, +}MmuMemoryType; + +typedef enum +{ + AM_Noaccess = 0, + AM_Read_Write, + AM_Read, +}MmuAccess; + +typedef enum +{ + AM_Shareable = 1, + AM_Nonshareable = 0 +}MmuShareability; + +struct AbstractionMmuDone +{ + int (*AbstractionMmuInit)(AbstractionMmu *mmu, uint32_t *ttb_base); + int (*AbstractionMmuSectionMap)(AbstractionMmu *mmu, uint32_t section_size); + int (*AbstractionMmuSectionUnmap)(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size); + int (*AbstractionMmuTtbSwitch)(AbstractionMmu *mmu); + int (*AbstracktonMmuTransform)(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr); +}; + +typedef struct +{ + uint32_t ttb_vbase; + uint32_t ttb_pbase; + + uint32_t vaddr_start; + uint32_t vaddr_end; + uint32_t paddr_start; + uint32_t paddr_end; + + uint32_t vpaddr_offset; + + uint32_t pte_attr; + uint32_t mmu_status; + + MmuMemoryType mmu_memory_type; + MmuAccess mmu_access; + MmuShareability mmu_shareability; + + struct AbstractionMmuDone *mmu_done; + + int lock; + int link_list; +}AbstractionMmu; \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/cache.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/cache.c index 5af33edcf..4a71e6c30 100755 --- a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/cache.c +++ b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/cache.c @@ -1,4 +1,23 @@ +/* +* Copyright (c) 2020 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: cache.c +* @brief: the general management of system cache +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/4/27 +* +*/ void InvalidInsCache() { diff --git a/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/mmu.c b/Ubiquitous/XiZi_AIoT/hardkernel/abstraction/mmu.c deleted file mode 100755 index e69de29bb..000000000 diff --git a/Ubiquitous/XiZi_AIoT/softkernel/memory/multiple-address-spaces/memory.c b/Ubiquitous/XiZi_AIoT/softkernel/memory/multiple-address-spaces/memory.c index e69de29bb..eb735195b 100644 --- a/Ubiquitous/XiZi_AIoT/softkernel/memory/multiple-address-spaces/memory.c +++ b/Ubiquitous/XiZi_AIoT/softkernel/memory/multiple-address-spaces/memory.c @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2020 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: memory.c +* @brief: the general management of system memory +* @version: 3.0 +* @author: AIIT XUOS Lab +* @date: 2023/4/27 +* +*/ \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m4/hc32f4a0/interrupt_vector.S b/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m4/hc32f4a0/interrupt_vector.S index 91e70665f..e38143b1d 100644 --- a/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m4/hc32f4a0/interrupt_vector.S +++ b/Ubiquitous/XiZi_IIoT/arch/arm/cortex-m4/hc32f4a0/interrupt_vector.S @@ -91,7 +91,7 @@ InterruptVectors: .long IsrEntry .long IsrEntry .long IsrEntry - .long IsrEntry + .long IRQ030_Handler .long IsrEntry .long IsrEntry .long IsrEntry diff --git a/Ubiquitous/XiZi_IIoT/board/cortex-m3-emulator/README.md b/Ubiquitous/XiZi_IIoT/board/cortex-m3-emulator/README.md index 3045cf738..8837deb62 100644 --- a/Ubiquitous/XiZi_IIoT/board/cortex-m3-emulator/README.md +++ b/Ubiquitous/XiZi_IIoT/board/cortex-m3-emulator/README.md @@ -188,7 +188,7 @@ sudo apt install gdb-multiarch qemu-system-arm -machine lm3s6965evb -nographic -kernel build/XiZi-cortex-m3-emulator.elf -s -S ``` -然后要重新开启另一个linux系统终端一个终端,执行`riscv-none-embed-gdb`命令 +然后要重新开启另一个linux系统终端一个终端,执行命令 ``` gdb-multiarch build/XiZi-cortex-m3-emulator.elf -ex "target remote localhost:1234" diff --git a/Ubiquitous/XiZi_IIoT/board/cortex-m4-emulator/README.md b/Ubiquitous/XiZi_IIoT/board/cortex-m4-emulator/README.md index f8d004f9a..b5b89263b 100644 --- a/Ubiquitous/XiZi_IIoT/board/cortex-m4-emulator/README.md +++ b/Ubiquitous/XiZi_IIoT/board/cortex-m4-emulator/README.md @@ -91,8 +91,8 @@ git clone https://gitlink.org.cn/xuos/xiuos.git 使用VScode打开代码,具体操作步骤为:在源码文件夹下打开系统终端,输入`code .`即可打开VScode开发环境,如下图所示: -
- +
+
@@ -145,14 +145,14 @@ make BOARD=cortex-m4-emulator menuconfig 2.在menuconfig界面配置需要关闭和开启的功能,按回车键进入下级菜单,按Y键选中需要开启的功能,按N键选中需要关闭的功能,配置结束后保存并退出(本例旨在演示简单的输出例程,所以没有需要配置的选项,双击快捷键ESC退出配置) -
- +
+
退出时选择`yes`保存上面所配置的内容,如下图所示: -
- +
+
3.继续执行以下命令,进行编译 @@ -183,8 +183,8 @@ qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4- QEMU运行起来后将会在终端上看到信息打印输出 -
- +
+
### 4.3 调试 @@ -204,5 +204,5 @@ qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4- 然后要重新开启另一个linux系统终端一个终端,执行`riscv-none-embed-gdb`命令 ``` -gdb-multiarch build/XiZi-cortex-m4-emulator.elf -ex "target remote localhost:1234" +gdb-multiarch build/XiZi-cortex-m4-emulator.elf -ex "target remote localhost:1234" ``` \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk b/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk index cf681ac77..0276e1286 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/config.mk @@ -1,9 +1,11 @@ export CROSS_COMPILE ?=/usr/bin/arm-none-eabi- -export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror +export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror +# export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2 export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds -export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror +export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -Werror +# export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror export APPLFLAGS := diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/Kconfig index f721032c6..fdc0b1c91 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/Kconfig @@ -1,74 +1,13 @@ -menuconfig BSP_USING_ADC1 - bool "Enable ADC1" - default y - if BSP_USING_ADC1 - config ADC1_BUS_NAME - string "adc 1 bus name" - default "adc1" +if BSP_USING_ADC + config ADC1_BUS_NAME + string "adc 1 bus name" + default "adc1" - config ADC1_DRIVER_NAME - string "adc 1 driver name" - default "adc1_drv" + config ADC1_DRIVER_NAME + string "adc 1 driver name" + default "adc1_drv" - config ADC1_DEVICE_NAME - string "adc 1 bus device name" - default "adc1_dev" - - config ADC1_GPIO_NUM - int "adc 1 gpio pin num" - default "0" - - config ADC1_GPIO_DEF - string "adc 1 gpio define type" - default "A" - endif - -menuconfig BSP_USING_ADC2 - bool "Enable ADC2" - default y - if BSP_USING_ADC2 - config ADC2_BUS_NAME - string "adc 2 bus name" - default "adc2" - - config ADC2_DRIVER_NAME - string "adc 2 driver name" - default "adc2_drv" - - config ADC2_DEVICE_NAME - string "adc 2 bus device name" - default "adc2_dev" - - config ADC2_GPIO_NUM - int "adc 2 gpio pin num" - default "6" - - config ADC2_GPIO_DEF - string "adc 2 gpio define type" - default "A" - endif - -menuconfig BSP_USING_ADC3 - bool "Enable ADC3" - default y - if BSP_USING_ADC3 - config ADC3_BUS_NAME - string "adc 3 bus name" - default "adc3" - - config ADC3_DRIVER_NAME - string "adc 3 driver name" - default "adc3_drv" - - config ADC3_DEVICE_NAME - string "adc 3 bus device name" - default "adc3_dev" - - config ADC3_GPIO_NUM - int "adc 3 gpio pin num" - default "0" - - config ADC3_GPIO_DEF - string "adc 3 gpio define type" - default "A" - endif + config ADC1_DEVICE_NAME + string "adc 1 bus device name" + default "adc1_dev" +endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/connect_adc.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/connect_adc.c index 620b21d8f..4e8b09475 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/connect_adc.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/adc/connect_adc.c @@ -20,79 +20,251 @@ #include -#define _ADC_CONS(string1, string2) string1##string2 -#define ADC_CONS(string1, string2) _ADC_CONS(string1, string2) +/******************************************************************************* + * Local pre-processor symbols/macros ('#define') + ******************************************************************************/ -#ifdef BSP_USING_ADC1 -#define ADC1_GPIO ADC_CONS(GPIO_Pin_, ADC1_GPIO_NUM) +/* The clock source of ADC. */ +#define ADC_CLK_SYS_CLK (1U) +#define ADC_CLK_PLLH (2U) +#define ADC_CLK_PLLA (3U) + +/* + * Selects a clock source according to the application requirements. + * PCLK4 is the clock for digital interface. + * PCLK2 is the clock for analog circuit. + * PCLK4 and PCLK2 are synchronous when the clock source is PLL. + * PCLK4 : PCLK2 = 1:1, 2:1, 4:1, 8:1, 1:2, 1:4. + * PCLK2 is in range [1MHz, 60MHz]. + * If the system clock is selected as the ADC clock, macro 'ADC_ADC_CLK' can only be defined as 'CLK_PERIPHCLK_PCLK'. + * If PLLH is selected as the ADC clock, macro 'ADC_ADC_CLK' can be defined as 'CLK_PERIPHCLK_PLLx'(x=Q, R). + * If PLLA is selected as the ADC clock, macro 'ADC_ADC_CLK' can be defined as 'CLK_PERIPHCLK_PLLXx'(x=P, Q, R). + */ +#define ADC_CLK_SEL (ADC_CLK_SYS_CLK) + +#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK) +#define ADC_CLK (CLK_PERIPHCLK_PCLK) + +#elif (ADC_CLK_SEL == ADC_CLK_PLLH) +#define ADC_CLK (CLK_PERIPHCLK_PLLQ) + +#elif (ADC_CLK_SEL == ADC_CLK_PLLA) +#define ADC_CLK (CLK_PERIPHCLK_PLLXP) + +#else +#error "The clock source your selected does not exist!!!" #endif -#ifdef BSP_USING_ADC2 -#define ADC2_GPIO ADC_CONS(GPIO_Pin_, ADC2_GPIO_NUM) -#endif +/* ADC unit instance for this example. */ +#define ADC_UNIT (CM_ADC1) +#define ADC_PERIPH_CLK (FCG3_PERIPH_ADC1) -#ifdef BSP_USING_ADC3 -#define ADC3_GPIO ADC_CONS(GPIO_Pin_, ADC3_GPIO_NUM) -#endif +/* Selects ADC channels that needed. */ +#define ADC_CH_POTENTIOMETER (ADC_CH3) +#define ADC_CH (ADC_CH_POTENTIOMETER) +#define ADC_CH_PORT (GPIO_PORT_A) +#define ADC_CH_PIN (GPIO_PIN_03) -static int AdcUdelay(uint32 us) +/* ADC sequence to be used. */ +#define ADC_SEQ (ADC_SEQ_A) +/* Flag of conversion end. */ +#define ADC_EOC_FLAG (ADC_FLAG_EOCA) + +/* ADC reference voltage. The voltage of pin VREFH. */ +#define ADC_VREF (3.3F) + +/* ADC accuracy(according to the resolution of ADC). */ +#define ADC_ACCURACY (1UL << 12U) + +/* Calculate the voltage(mV). */ +#define ADC_CAL_VOL(adcVal) (uint16_t)((((float32_t)(adcVal) * ADC_VREF) / ((float32_t)ADC_ACCURACY)) * 1000.F) + +/* Timeout value. */ +#define ADC_TIMEOUT_VAL (1000U) + +/** + * @brief Set specified ADC pin to analog mode. + * @param None + * @retval None + */ +static void AdcSetPinAnalogMode(void) { - uint32 ticks; - uint32 told, tnow, tcnt = 0; - uint32 reload = SysTick->LOAD; + stc_gpio_init_t stcGpioInit; - ticks = us * reload / (1000000 / TICK_PER_SECOND); - told = SysTick->VAL; - while (1) { - tnow = SysTick->VAL; - if (tnow != told) { - if (tnow < told) { - tcnt += told - tnow; - } else { - tcnt += reload - tnow + told; - } - told = tnow; - if (tcnt >= ticks) { - return 0; - break; - } - } - } + (void)GPIO_StructInit(&stcGpioInit); + stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG; + (void)GPIO_Init(ADC_CH_PORT, ADC_CH_PIN, &stcGpioInit); } -static uint16 GetAdcAverageValue(CM_ADC_TypeDef *ADCx, uint8 channel, uint8 times) +/** + * @brief Configures ADC clock. + * @param None + * @retval None + */ +static void AdcClockConfig(void) { - uint32 temp_val = 0; - int i; +#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK) + /* + * 1. Configures the clock divider of PCLK2 and PCLK4 here or in the function of configuring the system clock. + * In this example, the system clock is MRC@8MHz. + * PCLK4 is the digital interface clock, and PCLK2 is the analog circuit clock. + * Make sure that PCLK2 and PCLK4 meet the following conditions: + * PCLK4 : PCLK2 = 1:1, 2:1, 4:1, 8:1, 1:2, 1:4. + * PCLK2 is in range [1MHz, 60MHz]. + */ + CLK_SetClockDiv((CLK_BUS_PCLK2 | CLK_BUS_PCLK4), (CLK_PCLK2_DIV8 | CLK_PCLK4_DIV2)); - for(i = 0;i < times;i ++) { - temp_val += ADC_GetValue(ADCx, channel) & 0x0FFF; - KPrintf("GetAdcAverageValue val %u\n", ADC_GetValue(ADCx, channel)); - AdcUdelay(5000); - } - return temp_val / times; -} +#elif (ADC_CLK_SEL == ADC_CLK_PLLH) + /* + * 1. Configures PLLH and the divider of PLLHx(x=Q, R). + * PLLHx(x=Q, R) is used as both the digital interface clock and the analog circuit clock. + * PLLHx(x=Q, R) must be in range [1MHz, 60MHz] for ADC use. + * The input source of PLLH is XTAL(8MHz). + */ + stc_clock_pll_init_t stcPLLHInit; + stc_clock_xtal_init_t stcXtalInit; + /* Configures XTAL. PLLH input source is XTAL. */ + (void)CLK_XtalStructInit(&stcXtalInit); + stcXtalInit.u8State = CLK_XTAL_ON; + stcXtalInit.u8Drv = CLK_XTAL_DRV_ULOW; + stcXtalInit.u8Mode = CLK_XTAL_MD_OSC; + stcXtalInit.u8StableTime = CLK_XTAL_STB_499US; + (void)CLK_XtalInit(&stcXtalInit); + + (void)CLK_PLLStructInit(&stcPLLHInit); + /* + * PLLHx(x=Q, R) = ((PLL_source / PLLM) * PLLN) / PLLx + * PLLHQ = (8 / 1) * 80 /16 = 40MHz + * PLLHR = (8 / 1) * 80 /16 = 40MHz + */ + stcPLLHInit.u8PLLState = CLK_PLL_ON; + stcPLLHInit.PLLCFGR = 0UL; + stcPLLHInit.PLLCFGR_f.PLLM = (1UL - 1UL); + stcPLLHInit.PLLCFGR_f.PLLN = (80UL - 1UL); + stcPLLHInit.PLLCFGR_f.PLLP = (4UL - 1UL); + stcPLLHInit.PLLCFGR_f.PLLQ = (16UL - 1UL); + stcPLLHInit.PLLCFGR_f.PLLR = (16UL - 1UL); + /* stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL; */ + (void)CLK_PLLInit(&stcPLLHInit); + +#elif (ADC_CLK_SEL == ADC_CLK_PLLA) + /* + * 1. Configures PLLA and the divider of PLLAx(x=P, Q, R). + * PLLAx(x=P, Q, R) is used as both the digital interface clock and the analog circuit clock. + * PLLAx(x=P, Q, R) must be in range [1MHz, 60MHz] for ADC use. + * The input source of PLLA is HRC(16MHz). + */ + stc_clock_pllx_init_t stcPLLAInit; + + /* Enable HRC(16MHz) for PLLA. */ + CLK_HrcCmd(ENABLE); + + /* Specify the input source of PLLA. NOTE!!! PLLA and PLLH use the same input source. */ + CLK_SetPLLSrc(CLK_PLL_SRC_HRC); + /* PLLA configuration */ + (void)CLK_PLLxStructInit(&stcPLLAInit); + /* + * PLLAx(x=P, Q, R) = ((PLL_source / PLLM) * PLLN) / PLLx + * PLLAP = (16 / 2) * 40 / 8 = 40MHz + * PLLAQ = (16 / 2) * 40 / 10 = 32MHz + * PLLAR = (16 / 2) * 40 / 16 = 20MHz + */ + stcPLLAInit.u8PLLState = CLK_PLLX_ON; + stcPLLAInit.PLLCFGR = 0UL; + stcPLLAInit.PLLCFGR_f.PLLM = (2UL - 1UL); + stcPLLAInit.PLLCFGR_f.PLLN = (40UL - 1UL); + stcPLLAInit.PLLCFGR_f.PLLR = (8UL - 1UL); + stcPLLAInit.PLLCFGR_f.PLLQ = (10UL - 1UL); + stcPLLAInit.PLLCFGR_f.PLLP = (16UL - 1UL); + (void)CLK_PLLxInit(&stcPLLAInit); +#endif + /* 2. Specifies the clock source of ADC. */ + CLK_SetPeriClockSrc(ADC_CLK); +} + +/** + * @brief Initializes ADC. + * @param None + * @retval None + */ +static void AdcInitConfig(void) +{ + stc_adc_init_t stcAdcInit; + + /* 1. Enable ADC peripheral clock. */ + FCG_Fcg3PeriphClockCmd(ADC_PERIPH_CLK, ENABLE); + + /* 2. Modify the default value depends on the application. Not needed here. */ + (void)ADC_StructInit(&stcAdcInit); + + /* 3. Initializes ADC. */ + (void)ADC_Init(ADC_UNIT, &stcAdcInit); + + /* 4. ADC channel configuration. */ + /* 4.1 Set the ADC pin to analog input mode. */ + AdcSetPinAnalogMode(); + /* 4.2 Enable ADC channels. Call ADC_ChCmd() again to enable more channels if needed. */ + ADC_ChCmd(ADC_UNIT, ADC_SEQ, ADC_CH, ENABLE); + + /* 5. Conversion data average calculation function, if needed. + Call ADC_ConvDataAverageChCmd() again to enable more average channels if needed. */ + ADC_ConvDataAverageConfig(ADC_UNIT, ADC_AVG_CNT8); + ADC_ConvDataAverageChCmd(ADC_UNIT, ADC_CH, ENABLE); +} + +/** + * @brief Use ADC in polling mode. + * @param None + * @retval uint16_t u16AdcValue + */ +static uint16_t AdcPolling(void) +{ + uint16_t u16AdcValue = 0; + int32_t iRet = LL_ERR; + __IO uint32_t u32TimeCount = 0UL; + + /* Can ONLY start sequence A conversion. + Sequence B needs hardware trigger to start conversion. */ + ADC_Start(ADC_UNIT); + do { + if (ADC_GetStatus(ADC_UNIT, ADC_EOC_FLAG) == SET) { + ADC_ClearStatus(ADC_UNIT, ADC_EOC_FLAG); + iRet = LL_OK; + break; + } + } while (u32TimeCount++ < ADC_TIMEOUT_VAL); + + if (iRet == LL_OK) { + /* Get any ADC value of sequence A channel that needed. */ + u16AdcValue = ADC_GetValue(ADC_UNIT, ADC_CH); + KPrintf("The ADC value of potentiometer is %u, voltage is %u mV\r\n", + u16AdcValue, ADC_CAL_VOL(u16AdcValue)); + } else { + ADC_Stop(ADC_UNIT); + KPrintf("ADC exception.\r\n"); + } + + return ADC_CAL_VOL(u16AdcValue); +} static uint32 AdcOpen(void *dev) { x_err_t ret = EOK; - stc_adc_init_t stcAdcInit; - ADC_StructInit(&stcAdcInit); struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev; - CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data; - ADC_Init((ADCx),&stcAdcInit); + + AdcClockConfig(); + AdcInitConfig(); + return ret; } - static uint32 AdcClose(void *dev) { - // CM_ADC_TypeDef *adc_dev = (CM_ADC_TypeDef*)dev; struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev; - CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data; - + + ADC_Stop(ADC_UNIT); ADC_DeInit(ADCx); return EOK; @@ -100,19 +272,10 @@ static uint32 AdcClose(void *dev) static uint32 AdcRead(void *dev, struct BusBlockReadParam *read_param) { - struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev; + *(uint16 *)read_param->buffer = AdcPolling(); + read_param->read_length = 2; - struct HwAdc *adc_cfg = (struct HwAdc *)adc_dev->haldev.private_data; - - uint16 adc_average_value = 0; - uint8 times = 20; - - adc_average_value = GetAdcAverageValue(adc_cfg->ADCx, adc_cfg->adc_channel, times); - - *(uint16 *)read_param->buffer = adc_average_value; - read_param->read_length = 2; - - return read_param->read_length; + return EOK; } static uint32 AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info) @@ -131,9 +294,9 @@ static uint32 AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info { case OPE_CFG: adc_cfg->adc_channel = *(uint8 *)configure_info->private_data; - if (adc_cfg->adc_channel > 18) { - KPrintf("AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel); - adc_cfg->adc_channel = 0; + if (adc_cfg->adc_channel != 1) { + KPrintf("AdcDrvConfigure set adc channel(1) %u error!", adc_cfg->adc_channel); + adc_cfg->adc_channel = 1; ret = ERROR; } break; @@ -156,7 +319,7 @@ int HwAdcInit(void) { x_err_t ret = EOK; -#ifdef BSP_USING_ADC1 +#ifdef BSP_USING_ADC static struct AdcBus adc1_bus; static struct AdcDriver adc1_drv; static struct AdcHardwareDevice adc1_dev; @@ -183,7 +346,7 @@ int HwAdcInit(void) adc1_dev.adc_dev_done = &dev_done; adc1_cfg.ADCx = CM_ADC1; - adc1_cfg.adc_channel = 0; + adc1_cfg.adc_channel = 1; ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEVICE_NAME); if (ret != EOK) { @@ -197,88 +360,6 @@ int HwAdcInit(void) } #endif -#ifdef BSP_USING_ADC2 - static struct AdcBus adc2_bus; - static struct AdcDriver adc2_drv; - static struct AdcHardwareDevice adc2_dev; - static struct HwAdc adc2_cfg; - - adc2_drv.configure = AdcDrvConfigure; - - ret = AdcBusInit(&adc2_bus, ADC2_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC2 bus init error %d\n", ret); - return ERROR; - } - - ret = AdcDriverInit(&adc2_drv, ADC2_DRIVER_NAME); - if (ret != EOK) { - KPrintf("ADC2 driver init error %d\n", ret); - return ERROR; - } - ret = AdcDriverAttachToBus(ADC2_DRIVER_NAME, ADC2_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC2 driver attach error %d\n", ret); - return ERROR; - } - - adc2_dev.adc_dev_done = &dev_done; - adc2_cfg.ADCx = CM_ADC2; - adc2_cfg.adc_channel = 0; - - ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC2_DEVICE_NAME); - if (ret != EOK) { - KPrintf("ADC2 device register error %d\n", ret); - return ERROR; - } - ret = AdcDeviceAttachToBus(ADC2_DEVICE_NAME, ADC2_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC2 device register error %d\n", ret); - return ERROR; - } -#endif - -#ifdef BSP_USING_ADC3 - static struct AdcBus adc3_bus; - static struct AdcDriver adc3_drv; - static struct AdcHardwareDevice adc3_dev; - static struct HwAdc adc3_cfg; - - adc3_drv.configure = AdcDrvConfigure; - - ret = AdcBusInit(&adc3_bus, ADC3_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC3 bus init error %d\n", ret); - return ERROR; - } - - ret = AdcDriverInit(&adc3_drv, ADC3_DRIVER_NAME); - if (ret != EOK) { - KPrintf("ADC3 driver init error %d\n", ret); - return ERROR; - } - ret = AdcDriverAttachToBus(ADC3_DRIVER_NAME, ADC3_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC3 driver attach error %d\n", ret); - return ERROR; - } - - adc3_dev.adc_dev_done = &dev_done; - adc3_cfg.ADCx = CM_ADC3; - adc3_cfg.adc_channel = 0; - - ret = AdcDeviceRegister(&adc3_dev, (void *)&adc3_cfg, ADC3_DEVICE_NAME); - if (ret != EOK) { - KPrintf("ADC3 device register error %d\n", ret); - return ERROR; - } - ret = AdcDeviceAttachToBus(ADC3_DEVICE_NAME, ADC3_BUS_NAME); - if (ret != EOK) { - KPrintf("ADC3 device register error %d\n", ret); - return ERROR; - } -#endif - return ret; } diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile index 501d182d5..7254a2cb6 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/common/hc32_ll_driver/src/Makefile @@ -9,7 +9,7 @@ ifeq ($(CONFIG_BSP_USING_ADC),y) endif ifeq ($(CONFIG_BSP_USING_DAC),y) - SRC_FILES += hc32_ll_dac.c + SRC_FILES += hc32_ll_dac.c hc32_ll_mau.c endif ifeq ($(CONFIG_BSP_USING_SDIO),y) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/dac/connect_dac.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/dac/connect_dac.c index 3cbd220c3..efcc80743 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/dac/connect_dac.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/dac/connect_dac.c @@ -20,56 +20,301 @@ #include -#define _DAC_CONS(string1, string2) string1##string2 -#define DAC_CONS(string1, string2) _DAC_CONS(string1, string2) +/******************************************************************************* + * Local pre-processor symbols/macros ('#define') + ******************************************************************************/ +#define DAC_UNIT1_PORT (GPIO_PORT_A) +#define DAC_UNIT1_CHN1_PIN (GPIO_PIN_04) -#ifdef BSP_USING_DAC -#define DAC_GPIO DAC_CONS(GPIO_Pin_, DAC_GPIO_NUM) +#define VREFH (3.3F) +#define DAC_CHN1 (0U) +#define DAC_CHN2 (1U) +#define DAC_DATA_ALIGN_12b_R (0U) +#define DAC_DATA_ALIGN_12b_L (1U) + +#define SUPPORT_AMP +#define SUPPORT_ADP +#define SINGLE_WAVE_DAC_CHN (DAC_CHN1) +#define DAC_DATA_ALIGN (DAC_DATA_ALIGN_12b_L) + +#define SINE_DOT_NUMBER (4096U) +#define SINE_NEGATIVE_TO_POSITVE (1.0F) + +/******************************************************************************* + * Local type definitions ('typedef') + ******************************************************************************/ +typedef enum { + DAC_Unit1, + DAC_Unit2, + DAC_Unit_Max, +}en_dac_unit_t; + +typedef enum { + E_Dac_Single, + E_Dac_Dual, +}en_dac_cvt_t; + +typedef struct { + CM_DAC_TypeDef *pUnit; + en_dac_cvt_t enCvtType; + uint16_t u16Ch; +} stc_dac_handle_t; + +/******************************************************************************* + * Local variable definitions ('static') + ******************************************************************************/ +static stc_dac_handle_t m_stcDACHandle[DAC_Unit_Max] = {0}; +static uint32_t gu32SinTable[SINE_DOT_NUMBER]; +static stc_dac_handle_t *pSingleDac; + +/******************************************************************************* + * Function implementation - global ('extern') and local ('static') + ******************************************************************************/ +/** + * @brief MAU Initialization + * @param None + * @retval None + */ +static void MauInit(void) +{ + /* Enable MAU peripheral clock. */ + FCG_Fcg0PeriphClockCmd(PWC_FCG0_MAU, ENABLE); +} + +/** + * @brief MAU De-Initialization + * @param None + * @retval None + */ +static void MauDeinit(void) +{ + /* Enable MAU peripheral clock. */ + FCG_Fcg0PeriphClockCmd(PWC_FCG0_MAU, DISABLE); +} + +/** + * @brief Sin table Initialization + * @param [in] pSinTable sin table + * @param [in] u32count number of pSinTable items + * @retval None + */ +static void SinTableInit(uint32_t pSinTable[], uint32_t u32count) +{ + uint32_t i; + uint32_t u32AngAvg = (uint32_t)(float32_t)((float32_t)((float32_t)MAU_SIN_ANGIDX_TOTAL / (float32_t)u32count) + 0.5); + float32_t fSin; + for (i = 0U; i < u32count; i++) { + fSin = (((float32_t)MAU_Sin(CM_MAU, (uint16_t)(u32AngAvg * i)) + / (float32_t)MAU_SIN_Q15_SCALAR + SINE_NEGATIVE_TO_POSITVE) / VREFH) * + (float32_t)DAC_DATAREG_VALUE_MAX + 0.5F; + +#if (DAC_DATA_ALIGN == DAC_DATA_ALIGN_12b_L) + { + pSinTable[i] = (uint32_t)fSin << 4; + } +#else + { + pSinTable[i] = (uint32_t)fSin; + } #endif - + } +} + +/** + * @brief Enable DAC peripheral clock + * @param [in] enUnit The selected DAC unit + * @retval None + */ +static void DacPClkEnable(en_dac_unit_t enUnit) +{ + uint32_t u32PClk; + switch (enUnit) { + case DAC_Unit1: + u32PClk = PWC_FCG3_DAC1; + break; + case DAC_Unit2: + u32PClk = PWC_FCG3_DAC2; + break; + default: + u32PClk = PWC_FCG3_DAC1 | PWC_FCG3_DAC2; + break; + } + /* Enable DAC peripheral clock. */ + FCG_Fcg3PeriphClockCmd(u32PClk, ENABLE); +} + +/** + * @brief Init DAC single channel + * @param [in] enUnit The selected DAC unit + * @retval A pointer of DAC handler + */ +static stc_dac_handle_t *DacSingleConversionInit(en_dac_unit_t enUnit) +{ + uint8_t u8Port; + uint16_t u16Pin; + stc_dac_handle_t *pDac; + + if (enUnit == DAC_Unit1) { + pDac = &m_stcDACHandle[DAC_Unit1]; + pDac->pUnit = CM_DAC1; + } else { + pDac = &m_stcDACHandle[DAC_Unit2]; + pDac->pUnit = CM_DAC2; + } + DacPClkEnable(enUnit); + + pDac->enCvtType = E_Dac_Single; +#if (SINGLE_WAVE_DAC_CHN == DAC_CHN1) + pDac->u16Ch = DAC_CH1; +#else + pDac->u16Ch = DAC_CH2; +#endif + + /* Init DAC by default value: source from data register and output enabled*/ + DAC_DeInit(pDac->pUnit); + stc_dac_init_t stInit; + (void)DAC_StructInit(&stInit); + (void)DAC_Init(pDac->pUnit, pDac->u16Ch, &stInit); +#if (DAC_DATA_ALIGN == DAC_DATA_ALIGN_12b_L) + DAC_DataRegAlignConfig(pDac->pUnit, DAC_DATA_ALIGN_L); +#else + DAC_DataRegAlignConfig(pDac->pUnit, DAC_DATA_ALIGN_R); +#endif + + /* Set DAC pin attribute to analog */ + if (enUnit == DAC_Unit1) { + u8Port = DAC_UNIT1_PORT; +#if (SINGLE_WAVE_DAC_CHN == DAC_CHN1) + u16Pin = DAC_UNIT1_CHN1_PIN; +#endif + } + stc_gpio_init_t stcGpioInit; + (void)GPIO_StructInit(&stcGpioInit); + stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG; + (void)GPIO_Init(u8Port, u16Pin, &stcGpioInit); + +#ifdef SUPPORT_ADP + /* Set ADC first */ + /* Enable ADC peripheral clock. */ + FCG_Fcg3PeriphClockCmd(PWC_FCG3_ADC1 | PWC_FCG3_ADC2 | PWC_FCG3_ADC3, ENABLE); + if (CM_ADC1->STR == 0U) { + if (CM_ADC2->STR == 0U) { + if (CM_ADC3->STR == 0U) { + DAC_ADCPrioConfig(pDac->pUnit, DAC_ADP_SELECT_ALL, ENABLE); + DAC_ADCPrioCmd(pDac->pUnit, ENABLE); + } + } + } +#endif + return pDac; +} + +/** + * @brief Start single DAC conversions + * @param [in] pDac A pointer of DAC handler + * @retval None + */ +static void DacStartSingleConversion(const stc_dac_handle_t *pDac) +{ + /* Enalbe AMP */ +#ifdef SUPPORT_AMP + (void)DAC_AMPCmd(pDac->pUnit, pDac->u16Ch, ENABLE); +#endif + + (void)DAC_Start(pDac->pUnit, pDac->u16Ch); + +#ifdef SUPPORT_AMP + /* delay 3us before setting data*/ + DDL_DelayMS(1U); +#endif +} + +/** + * @brief Convert data by single DAC channel + * @param [in] pDac A pointer of DAC handler + * @param [in] pDataTable The data table to be converted + * @param [in] u32count Number of data table items + * @retval None + */ +__STATIC_INLINE void DacSetSingleConversionData(const stc_dac_handle_t *pDac, uint32_t const pDataTable[], uint32_t u32count) +{ + uint32_t i = 0U; + + for (i = 0U; i < u32count; i++) { +#ifdef SUPPORT_ADP + uint32_t u32TryCount = 100U; + while (u32TryCount != 0U) { + u32TryCount--; + if (SET != DAC_GetChConvertState(pDac->pUnit, pDac->u16Ch)) { + break; + } + } +#endif + DAC_SetChData(pDac->pUnit, pDac->u16Ch, (uint16_t)pDataTable[i]); + } +} + +/** + * @brief stop DAC conversion + * @param [in] pDac A pointer of DAC handler + * @retval None + */ +static void DAC_StopConversion(const stc_dac_handle_t *pDac) +{ + if (NULL == pDac) { + DAC_DeInit(CM_DAC1); + DAC_DeInit(CM_DAC2); + } else if (pDac->enCvtType != E_Dac_Dual) { + (void)DAC_Stop(pDac->pUnit, pDac->u16Ch); + } else { + DAC_StopDualCh(pDac->pUnit); + } +} static uint32 DacOpen(void *dev) { struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; - CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data; + /* Init MAU for generating sine data*/ + MauInit(); + /* Init sine data table */ + SinTableInit(gu32SinTable, SINE_DOT_NUMBER); - stc_dac_init_t pstcDacInit; - - DAC_StructInit(&pstcDacInit); - - DAC_Init(DACx,DAC_CH1,&pstcDacInit); + /* Init single DAC */ + pSingleDac = DacSingleConversionInit(DAC_Unit1); return EOK; } static uint32 DacClose(void *dev) { - struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; - CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data; - + + DAC_StopConversion(pSingleDac); + DAC_DeInit(DACx); + MauDeinit(); + + memset(gu32SinTable, 0 , sizeof(gu32SinTable)); + return EOK; } - -static uint32 DacRead(void *dev, struct BusBlockReadParam *read_param) +static uint32 DacWrite(void *dev, struct BusBlockWriteParam *write_param) { struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev; + struct HwDac *dac_cfg = (struct HwDac *)dac_dev->haldev.private_data; - CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data; + for (int i = 0; i < dac_cfg->digital_data; i ++) { + DacStartSingleConversion(pSingleDac); + DacSetSingleConversionData(pSingleDac, &gu32SinTable[i], 1U); + if (i > SINE_DOT_NUMBER) { + i = 0; + } + } - uint16 dac_set_value = 0; - - dac_set_value = DAC_GetChConvertState(DACx,DAC_CH1); - - *(uint16 *)read_param->buffer = dac_set_value; - read_param->read_length = 2; - - return read_param->read_length; return EOK; } @@ -88,8 +333,6 @@ static uint32 DacDrvConfigure(void *drv, struct BusConfigureInfo *configure_info { case OPE_CFG: dac_cfg->digital_data = *(uint16 *)configure_info->private_data; - // DAC_SetChannel1Data(DAC_Align_12b_R, dac_cfg->digital_data);//12 bits、R-Align data format, digital data - DAC_SetChData(dac_cfg->DACx,DAC_CH1,dac_cfg->digital_data); break; default: break; @@ -102,8 +345,8 @@ static const struct DacDevDone dev_done = { DacOpen, DacClose, + DacWrite, NONE, - DacRead, }; int HwDacInit(void) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/Makefile index b63aff8c2..385b69d4f 100755 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := ethernetif.c eth_driver.c +SRC_FILES := ethernetif.c eth_driver.c eth_netdev.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c index 69a76fa0a..25d106209 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_driver.c @@ -1,21 +1,22 @@ /** -* @file ethernetif.c -* @brief support edu-arm32-board ethernetif function and register to Lwip -* @version 3.0 -* @author AIIT XUOS Lab -* @date 2022-12-05 -*/ + * @file ethernetif.c + * @brief support hc32f4a0-board ethernetif function and register to Lwip + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022-12-05 + */ #include +#include #include #include -#include #include #include #include -void eth_irq_handler(void) { +void eth_irq_handler(void) +{ static x_base eth_irq_lock; eth_irq_lock = DISABLE_INTERRUPT(); @@ -24,7 +25,7 @@ void eth_irq_handler(void) { sys_sem_signal(get_eth_recv_sem()); ETH_DMA_ClearStatus(ETH_DMA_FLAG_RIS | ETH_DMA_FLAG_NIS); } - + ENABLE_INTERRUPT(eth_irq_lock); } @@ -35,7 +36,7 @@ void eth_irq_handler(void) { * - LL_OK: Initialize success * - LL_ERR: Initialize failed */ -int32_t low_level_init(struct netif *netif) +int32_t low_level_init(struct netif* netif) { int32_t i32Ret = LL_ERR; stc_eth_init_t stcEthInit; @@ -52,9 +53,9 @@ int32_t low_level_init(struct netif *netif) (void)ETH_StructInit(&stcEthInit); #ifdef ETH_INTERFACE_RMII - EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII; + EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII; #else - EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII; + EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII; #endif // stcEthInit.stcMacInit.u32ReceiveAll = ETH_MAC_RX_ALL_ENABLE; EthHandle.stcCommInit.u32ReceiveMode = ETH_RX_MD_INT; @@ -125,7 +126,7 @@ int32_t low_level_init(struct netif *netif) u16RegVal = PHY_PAGE_ADDR_0; (void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal); #endif - + return i32Ret; } @@ -137,19 +138,19 @@ int32_t low_level_init(struct netif *netif) * - LL_OK: The packet could be sent * - LL_ERR: The packet couldn't be sent */ -err_t low_level_output(struct netif *netif, struct pbuf *p) +err_t low_level_output(struct netif* netif, struct pbuf* p) { err_t i32Ret; - struct pbuf *q; - uint8_t *txBuffer; - __IO stc_eth_dma_desc_t *DmaTxDesc; + struct pbuf* q; + uint8_t* txBuffer; + __IO stc_eth_dma_desc_t* DmaTxDesc; uint32_t byteCnt; uint32_t frameLength = 0UL; uint32_t bufferOffset; uint32_t payloadOffset; DmaTxDesc = EthHandle.stcTxDesc; - txBuffer = (uint8_t *)((EthHandle.stcTxDesc)->u32Buf1Addr); + txBuffer = (uint8_t*)((EthHandle.stcTxDesc)->u32Buf1Addr); bufferOffset = 0UL; /* Copy frame from pbufs to driver buffers */ for (q = p; q != NULL; q = q->next) { @@ -165,28 +166,28 @@ err_t low_level_output(struct netif *netif, struct pbuf *p) /* Check if the length of data to copy is bigger than Tx buffer size */ while ((byteCnt + bufferOffset) > ETH_TX_BUF_SIZE) { /* Copy data to Tx buffer*/ - (void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset)); + (void)memcpy((uint8_t*)&(txBuffer[bufferOffset]), (uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset)); /* Point to next descriptor */ - DmaTxDesc = (stc_eth_dma_desc_t *)(DmaTxDesc->u32Buf2NextDescAddr); + DmaTxDesc = (stc_eth_dma_desc_t*)(DmaTxDesc->u32Buf2NextDescAddr); /* Check if the buffer is available */ if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) { i32Ret = (err_t)ERR_USE; goto error; } - txBuffer = (uint8_t *)(DmaTxDesc->u32Buf1Addr); + txBuffer = (uint8_t*)(DmaTxDesc->u32Buf1Addr); byteCnt = byteCnt - (ETH_TX_BUF_SIZE - bufferOffset); payloadOffset = payloadOffset + (ETH_TX_BUF_SIZE - bufferOffset); frameLength = frameLength + (ETH_TX_BUF_SIZE - bufferOffset); bufferOffset = 0UL; } /* Copy the remaining bytes */ - (void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), byteCnt); + (void)memcpy((uint8_t*)&(txBuffer[bufferOffset]), (uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), byteCnt); bufferOffset = bufferOffset + byteCnt; frameLength = frameLength + byteCnt; } /* Prepare transmit descriptors to give to DMA */ - if(LL_OK != ETH_DMA_SetTransFrame(&EthHandle, frameLength)) { + if (LL_OK != ETH_DMA_SetTransFrame(&EthHandle, frameLength)) { KPrintf("[%s] Error sending eth DMA frame\n", __func__); } i32Ret = (err_t)ERR_OK; @@ -208,13 +209,13 @@ error: * @param netif The network interface structure for this ethernetif. * @retval A pbuf filled with the received packet (including MAC header) or NULL on memory error. */ -struct pbuf *low_level_input(struct netif *netif) +struct pbuf* low_level_input(struct netif* netif) { - struct pbuf *p = NULL; - struct pbuf *q; + struct pbuf* p = NULL; + struct pbuf* q; uint32_t len; - uint8_t *rxBuffer; - __IO stc_eth_dma_desc_t *DmaRxDesc; + uint8_t* rxBuffer; + __IO stc_eth_dma_desc_t* DmaRxDesc; uint32_t byteCnt; uint32_t bufferOffset; uint32_t payloadOffset; @@ -227,7 +228,7 @@ struct pbuf *low_level_input(struct netif *netif) /* Obtain the size of the packet */ len = (EthHandle.stcRxFrame).u32Len; - rxBuffer = (uint8_t *)(EthHandle.stcRxFrame).u32Buf; + rxBuffer = (uint8_t*)(EthHandle.stcRxFrame).u32Buf; if (len > 0UL) { /* Allocate a pbuf chain of pbufs from the buffer */ p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); @@ -243,17 +244,17 @@ struct pbuf *low_level_input(struct netif *netif) /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */ while ((byteCnt + bufferOffset) > ETH_RX_BUF_SIZE) { /* Copy data to pbuf */ - (void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset)); + (void)memcpy((uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (uint8_t*)&(rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset)); /* Point to next descriptor */ - DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr); - rxBuffer = (uint8_t *)(DmaRxDesc->u32Buf1Addr); + DmaRxDesc = (stc_eth_dma_desc_t*)(DmaRxDesc->u32Buf2NextDescAddr); + rxBuffer = (uint8_t*)(DmaRxDesc->u32Buf1Addr); byteCnt = byteCnt - (ETH_RX_BUF_SIZE - bufferOffset); payloadOffset = payloadOffset + (ETH_RX_BUF_SIZE - bufferOffset); bufferOffset = 0UL; } /* Copy remaining data in pbuf */ - (void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), byteCnt); + (void)memcpy((uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (uint8_t*)&(rxBuffer[bufferOffset]), byteCnt); bufferOffset = bufferOffset + byteCnt; } } @@ -261,7 +262,7 @@ struct pbuf *low_level_input(struct netif *netif) DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc; for (i = 0UL; i < (EthHandle.stcRxFrame).u32SegCount; i++) { DmaRxDesc->u32ControlStatus |= ETH_DMA_RXDESC_OWN; - DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr); + DmaRxDesc = (stc_eth_dma_desc_t*)(DmaRxDesc->u32Buf2NextDescAddr); } /* Clear Segment_Count */ (EthHandle.stcRxFrame).u32SegCount = 0UL; @@ -277,11 +278,10 @@ struct pbuf *low_level_input(struct netif *netif) return p; } -extern void LwipSetIPTest(int argc, char *argv[]); -int HwEthInit(void) { -// lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - LwipSetIPTest(1, NULL); - return EOK; +extern void LwipSetIPTest(int argc, char* argv[]); +int HwEthInit(void) +{ + // lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); + LwipSetIPTest(1, NULL); + return EOK; } - - diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c new file mode 100644 index 000000000..1c5c9d3c5 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/eth_netdev.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/** +* @file eth_netdev.c +* @brief register net dev function for lwip +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +#include +#include +#include +#include +#include +#include + +static const uint32_t NETIF_NAME_LEN = 2; + +static int lwip_netdev_set_up(struct netdev* netdev) +{ + netif_set_up((struct netif*)netdev->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev* netif) +{ + netif_set_down((struct netif*)netif->user_data); + return ERR_OK; +} + +#ifndef ip_2_ip4 +#define ip_2_ip4(ipaddr) (ipaddr) +#endif +static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw) +{ + if (ip_addr && netmask && gw) { + netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } else { + if (ip_addr) { + netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr)); + } + if (netmask) { + netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask)); + } + if (gw) { + netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); + } + } +} + +#ifdef LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server) +{ +#if LWIP_VERSION_MAJOR == 1U /* v1.x */ + extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver); +#else /* >=2.x */ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server); +#endif /* LWIP_VERSION_MAJOR == 1U */ + + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif + +#ifdef LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) +{ + netdev_low_level_set_dhcp_status(netdev, is_enabled); + + if (true == is_enabled) { + dhcp_start((struct netif*)netdev->user_data); + } else { + dhcp_stop((struct netif*)netdev->user_data); + } + + return ERR_OK; +} +#endif + +static int lwip_netdev_set_default(struct netdev* netdev) +{ + netif_set_default((struct netif*)netdev->user_data); + return ERR_OK; +} + +static const struct netdev_ops lwip_netdev_ops = { + .set_up = lwip_netdev_set_up, + .set_down = lwip_netdev_set_down, + .set_addr_info = lwip_netdev_set_addr_info, +#ifdef LWIP_DNS + .set_dns_server = lwip_netdev_set_dns_server, +#endif +#ifdef LWIP_DHCP + .set_dhcp = lwip_netdev_set_dhcp, +#endif + .set_default = lwip_netdev_set_default, +}; + +static inline int netdev_set_flags(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + struct netdev* netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == NULL) { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + // set flags + if (lwip_netif->flags | NETIF_FLAG_BROADCAST) { + netdev->flags |= NETDEV_FLAG_BROADCAST; + } + if (lwip_netif->flags | NETIF_FLAG_ETHARP) { + netdev->flags |= NETDEV_FLAG_ETHARP; + } + if (lwip_netif->flags | NETIF_FLAG_IGMP) { + netdev->flags |= NETDEV_FLAG_IGMP; + } +#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */ + if (lwip_netif->flags & NETIF_FLAG_MLD6) { + netdev->flags |= NETDEV_FLAG_MLD6; + } +#endif /* LWIP_VERSION_MAJOR >= 2U */ + +#if LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, true); +#else + netdev_low_level_set_dhcp_status(netdev, false); +#endif + + return ERR_OK; +} + +int lwip_netdev_add(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + + struct netdev* netdev = calloc(1, sizeof(struct netdev)); + if (netdev == NULL) { + return -ERR_IF; + } + + // init netdev + char netif_name[NETIF_NAME_LEN + 1]; + strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN); + // register netdev + int result = netdev_register(netdev, netif_name, (void*)lwip_netif); + // set values of netdev + netdev_set_flags(lwip_netif); + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + + return result; +} + +void lwip_netdev_del(struct netif* lwip_netif) +{ + char name[NETIF_NAME_LEN + 1]; + struct netdev* netdev; + + CHECK(lwip_netif); + + strncpy(name, lwip_netif->name, NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + free(netdev); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/ethernetif.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/ethernetif.c index 1e50cdfab..ec463faab 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/ethernet/ethernetif.c @@ -19,21 +19,21 @@ */ /** -* @file ethernetif.c -* @brief support edu-arm32-board ethernetif function and register to Lwip -* @version 3.0 -* @author AIIT XUOS Lab -* @date 2022-12-05 -*/ + * @file ethernetif.c + * @brief support hc32f4a0-board ethernetif function and register to Lwip + * @version 3.0 + * @author AIIT XUOS Lab + * @date 2022-12-05 + */ /************************************************* File name: ethernetif.c Description: support edu-arm32-board ethernetif configure and register to Lwip Others: take projects\ev_hc32f4a0_lqfp176\examples\eth\eth_loopback\source\ethernetif.c for references -History: +History: 1. Date: 2022-12-05 Author: AIIT XUOS Lab -Modification: +Modification: 1、include harware_ethernetif.h、hc32_ll_eth.h、hc32_ll_gpio.h、hc32_ll_utility.h、hc32_ll_fcg.h and lwip H files; 2、modify ethernetif_init as err_t; 3、add ETH_RST_PORT and ETH_RST_PIN; @@ -47,13 +47,15 @@ Modification: * Include files ******************************************************************************/ #include +#include #include #include -#include #include #include +#include #include +#include /** * @addtogroup HC32F4A0_DDL_Examples @@ -73,7 +75,6 @@ Modification: * Local pre-processor symbols/macros ('#define') ******************************************************************************/ - /******************************************************************************* * Global variable definitions (declared in header file with 'extern') ******************************************************************************/ @@ -86,7 +87,6 @@ Modification: * Local variable definitions ('static') ******************************************************************************/ - /******************************************************************************* * Function implementation - global ('extern') and local ('static') ******************************************************************************/ @@ -180,41 +180,14 @@ void Ethernet_GpioInit(void) #endif } -void *ethernetif_config_enet_set(uint8_t enet_port) { +void* ethernetif_config_enet_set(uint8_t enet_port) +{ return NONE; } -void Time_Update_LwIP(void) { - //no need to do -} - -/** - * @brief Should be called at the beginning of the program to set up the network interface. - * @param netif The network interface structure for this ethernetif. - * @retval err_t: - * - LL_OK: The IF is initialized - * - LL_ERR: The IF is uninitialized - */ -err_t ethernetif_init(struct netif *netif) +void Time_Update_LwIP(void) { -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - netif->hostname = "lwip"; -#endif /* LWIP_NETIF_HOSTNAME */ - netif->name[0] = IFNAME0; - netif->name[1] = IFNAME1; - -#ifndef ETHERNET_LOOPBACK_TEST - /* We directly use etharp_output() here to save a function call. - * You can instead declare your own function an call etharp_output() - * from it if you have to do some checks before sending (e.g. if link - * is available...) */ - netif->output = etharp_output; - netif->linkoutput = low_level_output; -#endif - - /* initialize the hardware */ - return low_level_init(netif); + // no need to do } /** @@ -222,16 +195,16 @@ err_t ethernetif_init(struct netif *netif) * @param netif The network interface structure for this ethernetif. * @retval None */ -void ethernetif_input(void *netif_arg) +void ethernetif_input(void* netif_arg) { - struct pbuf *p; - struct netif *netif = (struct netif *)netif_arg; + struct pbuf* p; + struct netif* netif = (struct netif*)netif_arg; x_base critical_lock; /* Move received packet into a new pbuf */ while (1) { sys_arch_sem_wait(get_eth_recv_sem(), WAITING_FOREVER); - while(1) { + while (1) { p = low_level_input(netif); #ifndef ETHERNET_LOOPBACK_TEST /* Entry point to the LwIP stack */ @@ -256,12 +229,51 @@ void ethernetif_input(void *netif_arg) } } +/** + * @brief Should be called at the beginning of the program to set up the network interface. + * @param netif The network interface structure for this ethernetif. + * @retval err_t: + * - LL_OK: The IF is initialized + * - LL_ERR: The IF is uninitialized + */ +err_t ethernetif_init(struct netif* netif) +{ +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + netif->hostname = "lwip"; +#endif /* LWIP_NETIF_HOSTNAME */ + netif->name[0] = IFNAME0; + netif->name[1] = IFNAME1; + +#ifndef ETHERNET_LOOPBACK_TEST + /* We directly use etharp_output() here to save a function call. + * You can instead declare your own function an call etharp_output() + * from it if you have to do some checks before sending (e.g. if link + * is available...) */ + netif->output = etharp_output; + netif->linkoutput = low_level_output; + // netif->linkoutput = ethernetif_linkoutput; +#endif + + /* initialize the hardware */ + if (LL_OK != low_level_init(netif)) { + return LL_ERR; + } + + if (EOK != lwip_netdev_add(netif)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__)); + } else { + // printf("[%s] Add Netdev successful\n", __func__); + } + return LL_OK; +} + /** * @brief Check the netif link status. * @param netif the network interface * @retval None */ -void EthernetIF_CheckLink(struct netif *netif) +void EthernetIF_CheckLink(struct netif* netif) { uint16_t u16RegVal = 0U; static uint8_t u8PreStatus = 0U; @@ -296,7 +308,7 @@ void EthernetIF_CheckLink(struct netif *netif) * @param netif The network interface. * @retval None */ -void EthernetIF_UpdateLink(struct netif *netif) +void EthernetIF_UpdateLink(struct netif* netif) { uint16_t u16RegVal; @@ -337,7 +349,7 @@ void EthernetIF_UpdateLink(struct netif *netif) * @param netif The network interface * @retval None */ -void EthernetIF_PeriodicHandle(struct netif *netif) +void EthernetIF_PeriodicHandle(struct netif* netif) { #ifndef ETH_INTERFACE_RMII uint32_t curTick; @@ -358,7 +370,7 @@ void EthernetIF_PeriodicHandle(struct netif *netif) * @param netif The network interface * @retval None */ -void EthernetIF_LinkCallback(struct netif *netif) +void EthernetIF_LinkCallback(struct netif* netif) { __IO uint32_t tickStart = 0UL; uint16_t u16RegVal = 0U; @@ -405,8 +417,7 @@ void EthernetIF_LinkCallback(struct netif *netif) CLR_REG16_BIT(u16RegVal, PHY_FULLDUPLEX_100M); /* Set MAC Speed and Duplex Mode to PHY */ (void)ETH_PHY_WriteReg(&EthHandle, PHY_BCR, - ((uint16_t)((EthHandle.stcCommInit).u32DuplexMode >> 3U) | - (uint16_t)((EthHandle.stcCommInit).u32Speed >> 1U) | u16RegVal)); + ((uint16_t)((EthHandle.stcCommInit).u32DuplexMode >> 3U) | (uint16_t)((EthHandle.stcCommInit).u32Speed >> 1U) | u16RegVal)); } /* ETH MAC Re-Configuration */ ETH_MAC_SetDuplexSpeed((EthHandle.stcCommInit).u32DuplexMode, (EthHandle.stcCommInit).u32Speed); @@ -427,7 +438,7 @@ void EthernetIF_LinkCallback(struct netif *netif) * - LL_OK: The IF is link up * - LL_ERR: The IF is link down */ -int32_t EthernetIF_IsLinkUp(struct netif *netif) +int32_t EthernetIF_IsLinkUp(struct netif* netif) { return (0U != u8PhyLinkStatus) ? LL_OK : LL_ERR; } @@ -437,14 +448,14 @@ int32_t EthernetIF_IsLinkUp(struct netif *netif) * @param netif The network interface * @retval None */ -__WEAKDEF void EthernetIF_NotifyLinkChange(struct netif *netif) +__WEAKDEF void EthernetIF_NotifyLinkChange(struct netif* netif) { /* This is function could be implemented in user file when the callback is needed */ if (LL_OK == EthernetIF_IsLinkUp(netif)) { GPIO_SetPins(ETH_LINK_LED_PORT, ETH_LINK_LED_PIN); } else { GPIO_ResetPins(ETH_LINK_LED_PORT, ETH_LINK_LED_PIN); - } + } } /** @@ -453,7 +464,8 @@ __WEAKDEF void EthernetIF_NotifyLinkChange(struct netif *netif) * @param p The MAC packet to receive * @retval None */ -__WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p) { +__WEAKDEF void EthernetIF_InputCallback(struct netif* netif, struct pbuf* p) +{ /* This is function could be implemented in user file when the callback is needed */ #ifdef ETHERNET_LOOPBACK_TEST if ((0 == (memcmp(p->payload, txPbuf.payload, p->len))) && (p->len == txPbuf.len)) { @@ -479,7 +491,7 @@ __WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p) { #ifdef ETHERNET_LOOPBACK_TEST -static void EthLoopBackTask(void *parameter) +static void EthLoopBackTask(void* parameter) { while (1) { if (RESET == GPIO_ReadInputPins(USER_KEY_PORT, USER_KEY_PIN)) { @@ -489,7 +501,7 @@ static void EthLoopBackTask(void *parameter) } } - //KPrintf("ready to receive eth loop back data\n"); + // KPrintf("ready to receive eth loop back data\n"); /* Read a received packet */ ethernetif_input(&testnetif); /* Handle periodic timers */ @@ -514,24 +526,24 @@ static void EthLoopBackTest(void) (void)ethernetif_init(&testnetif); /* fill data to txPbuf */ - txPbuf.next = NULL; + txPbuf.next = NULL; txPbuf.payload = txBuf; - txPbuf.len = strlen(txBuf); + txPbuf.len = strlen(txBuf); int eth_loopback_task = 0; eth_loopback_task = KTaskCreate("eth_loopback", EthLoopBackTask, NONE, - 2048, 8); - if(eth_loopback_task < 0) { - KPrintf("eth_loopback_task create failed ...%s %d.\n", __FUNCTION__,__LINE__); - return; - } + 2048, 8); + if (eth_loopback_task < 0) { + KPrintf("eth_loopback_task create failed ...%s %d.\n", __FUNCTION__, __LINE__); + return; + } StartupKTask(eth_loopback_task); return; } -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), -EthLoopBackTest, EthLoopBackTest, EthLoopBackTest); +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + EthLoopBackTest, EthLoopBackTest, EthLoopBackTest); #endif diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/i2c/connect_i2c.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/i2c/connect_i2c.c index d59f7b98b..20149f915 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/i2c/connect_i2c.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/i2c/connect_i2c.c @@ -117,6 +117,9 @@ static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info static uint32 I2cMasterWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) { + if (msg->len == 0) { + return EOK; + } uint32 i32Ret; I2C_Cmd(I2C_UNIT, ENABLE); @@ -171,6 +174,9 @@ static uint32 I2cMasterReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDat } static uint32 I2cSlaveWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) { + if (msg->len == 0) { + return EOK; + } uint32 i32Ret; I2C_Cmd(I2C_UNIT, ENABLE); @@ -222,7 +228,7 @@ static uint32 I2cSlaveReadData(struct I2cHardwareDevice *i2c_dev, struct I2cData if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) { /* Slave receive data*/ i32Ret = I2C_ReceiveData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT); - KPrintf("Slave receive success!\r\n"); + KPrintf("Slave receive success!\r\n"); if ((LL_OK == i32Ret) || (LL_ERR_TIMEOUT == i32Ret)) { /* Wait stop condition */ @@ -336,7 +342,7 @@ int HwI2cInit(void) return ret; } -//#define I2C_TEST +// #define I2C_TEST #ifdef I2C_TEST #define USER_KEY_PORT (GPIO_PORT_I) diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_dac.h b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_dac.h index 1108fcfdb..c99f28010 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_dac.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_dac.h @@ -34,13 +34,6 @@ struct HwDac uint16 digital_data; }; -typedef struct { - CM_DAC_TypeDef *pUnit; - // en_dac_cvt_t enCvtType; - uint16_t u16Ch; -} stc_dac_handle_t; - - int HwDacInit(void); #ifdef __cplusplus diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_ethernet.h index 7fae45a9f..4f0529a0b 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/include/connect_ethernet.h @@ -1,40 +1,39 @@ /* -* Copyright (c) 2021 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. -*/ + * Copyright (c) 2021 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 connect_ethernet.h -* @brief Adapted network software protocol stack and hardware operation functions -* @version 2.0 -* @author AIIT XUOS Lab -* @date 2022-12-05 -*/ + * @file connect_ethernet.h + * @brief Adapted network software protocol stack and hardware operation functions + * @version 2.0 + * @author AIIT XUOS Lab + * @date 2022-12-05 + */ #ifndef CONNECT_ETHERNET_H #define CONNECT_ETHERNET_H #include "hardware_ethernetif.h" -#include -#include #include +#include +#include #ifdef __cplusplus - extern "C" { +extern "C" { #endif -struct hc32_irq_config -{ - IRQn_Type irq_num; - uint32_t irq_prio; - en_int_src_t int_src; +struct hc32_irq_config { + IRQn_Type irq_num; + uint32_t irq_prio; + en_int_src_t int_src; }; /* Global Ethernet handle*/ @@ -52,22 +51,23 @@ __ALIGN_BEGIN static uint8_t EthRxBuff[ETH_RX_BUF_NUM][ETH_RX_BUF_SIZE]; static uint8_t u8PhyLinkStatus = 0U, u8EthInitStatus = 0U; static struct Hc32IrqConfig eth_irq_config = { - .irq_num = BSP_ETH_IRQ_NUM, - .irq_prio = BSP_ETH_IRQ_PRIO, - .int_src = INT_SRC_ETH_GLB_INT, + .irq_num = BSP_ETH_IRQ_NUM, + .irq_prio = BSP_ETH_IRQ_PRIO, + .int_src = INT_SRC_ETH_GLB_INT, }; void Ethernet_GpioInit(void); -int32_t low_level_init(struct netif *netif); -err_t low_level_output(struct netif *netif, struct pbuf *p); -struct pbuf *low_level_input(struct netif *netif); +int32_t low_level_init(struct netif* netif); +err_t low_level_output(struct netif* netif, struct pbuf* p); +struct pbuf* low_level_input(struct netif* netif); + +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); int HwEthInit(void); - #ifdef __cplusplus } #endif #endif - diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/Kconfig b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/Kconfig index 7f51f8e7b..626811be0 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/Kconfig @@ -13,6 +13,21 @@ menuconfig BSP_USING_UART3 default "usart3_dev3" endif +menuconfig BSP_USING_UART4 + bool "Enable USART4 for RS485" + default y + if BSP_USING_UART4 + config SERIAL_BUS_NAME_4 + string "serial bus 4 name" + default "usart4" + config SERIAL_DRV_NAME_4 + string "serial bus 4 driver name" + default "usart4_drv" + config SERIAL_4_DEVICE_NAME_0 + string "serial bus 4 device 0 name" + default "usart4_dev4" + endif + menuconfig BSP_USING_UART6 bool "Enable USART6" default n diff --git a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/connect_usart.c b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/connect_usart.c index 47a9ca68a..b16c709bd 100644 --- a/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/connect_usart.c +++ b/Ubiquitous/XiZi_IIoT/board/edu-arm32/third_party_driver/usart/connect_usart.c @@ -50,6 +50,14 @@ Modification: #define USART3_TX_PIN (GPIO_PIN_10) #endif +#if defined(BSP_USING_UART4) +#define USART4_RX_PORT (GPIO_PORT_E) +#define USART4_RX_PIN (GPIO_PIN_07) + +#define USART4_TX_PORT (GPIO_PORT_G) +#define USART4_TX_PIN (GPIO_PIN_00) +#endif + #if defined(BSP_USING_UART6) #define USART6_RX_PORT (GPIO_PORT_H) #define USART6_RX_PIN (GPIO_PIN_06) @@ -72,6 +80,12 @@ static x_err_t UartGpioInit(CM_USART_TypeDef *USARTx) GPIO_SetFunc(USART3_TX_PORT, USART3_TX_PIN, GPIO_FUNC_32); break; #endif +#ifdef BSP_USING_UART4 + case (uint32)CM_USART4: + GPIO_SetFunc(USART4_RX_PORT, USART4_RX_PIN, GPIO_FUNC_33); + GPIO_SetFunc(USART4_TX_PORT, USART4_TX_PIN, GPIO_FUNC_32); + break; +#endif #ifdef BSP_USING_UART6 case (uint32)CM_USART6: GPIO_SetFunc(USART6_RX_PORT, USART6_RX_PIN, GPIO_FUNC_37); @@ -123,6 +137,32 @@ void Uart3RxErrIrqHandler(void) } #endif +#ifdef BSP_USING_UART4 +struct SerialBus serial_bus_4; +struct SerialDriver serial_driver_4; +struct SerialHardwareDevice serial_device_4; + +void Uart4RxIrqHandler(void) +{ + x_base lock = 0; + lock = DISABLE_INTERRUPT(); + + SerialSetIsr(&serial_device_4, SERIAL_EVENT_RX_IND); + + ENABLE_INTERRUPT(lock); +} + +void Uart4RxErrIrqHandler(void) +{ + x_base lock = 0; + lock = DISABLE_INTERRUPT(); + + UartRxErrIsr(&serial_bus_4, &serial_driver_4, &serial_device_4); + + ENABLE_INTERRUPT(lock); +} +#endif + #ifdef BSP_USING_UART6 struct SerialBus serial_bus_6; struct SerialDriver serial_driver_6; @@ -499,6 +539,57 @@ int HwUsartInit(void) } #endif +#ifdef BSP_USING_UART4 + static struct SerialCfgParam serial_cfg_4; + memset(&serial_cfg_4, 0, sizeof(struct SerialCfgParam)); + + static struct SerialDevParam serial_dev_param_4; + memset(&serial_dev_param_4, 0, sizeof(struct SerialDevParam)); + + static struct UsartHwCfg serial_hw_cfg_4; + memset(&serial_hw_cfg_4, 0, sizeof(struct UsartHwCfg)); + + serial_driver_4.drv_done = &drv_done; + serial_driver_4.configure = SerialDrvConfigure; + serial_device_4.hwdev_done = &hwdev_done; + + serial_cfg_4.data_cfg = data_cfg_init; + + //default irq configure + serial_hw_cfg_4.uart_device = CM_USART4; + serial_hw_cfg_4.usart_clock = FCG3_PERIPH_USART4; + serial_hw_cfg_4.rx_err_irq.irq_config.irq_num = BSP_UART4_RXERR_IRQ_NUM; + serial_hw_cfg_4.rx_err_irq.irq_config.irq_prio = BSP_UART4_RXERR_IRQ_PRIO; + serial_hw_cfg_4.rx_err_irq.irq_config.int_src = INT_SRC_USART4_EI; + + serial_hw_cfg_4.rx_irq.irq_config.irq_num = BSP_UART4_RX_IRQ_NUM; + serial_hw_cfg_4.rx_irq.irq_config.irq_prio = BSP_UART4_RX_IRQ_PRIO; + serial_hw_cfg_4.rx_irq.irq_config.int_src = INT_SRC_USART4_RI; + + serial_hw_cfg_4.rx_err_irq.irq_callback = Uart4RxErrIrqHandler; + serial_hw_cfg_4.rx_irq.irq_callback = Uart4RxIrqHandler; + + hc32_install_irq_handler(&serial_hw_cfg_4.rx_err_irq.irq_config, serial_hw_cfg_4.rx_err_irq.irq_callback, 0); + + serial_cfg_4.hw_cfg.private_data = (void *)&serial_hw_cfg_4; + serial_driver_4.private_data = (void *)&serial_cfg_4; + + serial_dev_param_4.serial_work_mode = SIGN_OPER_INT_RX; + serial_device_4.haldev.private_data = (void *)&serial_dev_param_4; + + ret = BoardSerialBusInit(&serial_bus_4, &serial_driver_4, SERIAL_BUS_NAME_4, SERIAL_DRV_NAME_4); + if (EOK != ret) { + KPrintf("HwUartInit uart4 error ret %u\n", ret); + return ERROR; + } + + ret = BoardSerialDevBend(&serial_device_4, (void *)&serial_cfg_4, SERIAL_BUS_NAME_4, SERIAL_4_DEVICE_NAME_0); + if (EOK != ret) { + KPrintf("HwUartInit uart4 error ret %u\n", ret); + return ERROR; + } +#endif + #ifdef BSP_USING_UART6 static struct SerialCfgParam serial_cfg_6; memset(&serial_cfg_6, 0, sizeof(struct SerialCfgParam)); diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/Makefile index 1df7f37e7..968713ab4 100755 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c fsl_enet_qos.c +SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c fsl_enet_qos.c eth_netdev.c SRC_DIR := phy mdio include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/enet_ethernetif.c index b7bf34f03..ac69b5cc0 100644 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/enet_ethernetif.c @@ -353,5 +353,11 @@ err_t ethernetif_init(struct netif *netif, } #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__)); + if (EOK != lwip_netdev_add(netif)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__)); + } else { + printf("[%s] Add Netdev successful\n", __func__); + } return ERR_OK; } diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c new file mode 100644 index 000000000..03ca27594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/ethernet/eth_netdev.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/** +* @file eth_netdev.c +* @brief register net dev function for lwip +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +#include +#include +#include +#include +#include +#include + +static const uint32_t NETIF_NAME_LEN = 2; + +static int lwip_netdev_set_up(struct netdev* netdev) +{ + netif_set_up((struct netif*)netdev->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev* netif) +{ + netif_set_down((struct netif*)netif->user_data); + return ERR_OK; +} + +#ifndef ip_2_ip4 +#define ip_2_ip4(ipaddr) (ipaddr) +#endif +static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw) +{ + if (ip_addr && netmask && gw) { + netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } else { + if (ip_addr) { + netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr)); + } + if (netmask) { + netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask)); + } + if (gw) { + netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); + } + } +} + +#ifdef LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server) +{ +#if LWIP_VERSION_MAJOR == 1U /* v1.x */ + extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver); +#else /* >=2.x */ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server); +#endif /* LWIP_VERSION_MAJOR == 1U */ + + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif + +#ifdef LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) +{ + netdev_low_level_set_dhcp_status(netdev, is_enabled); + + if (true == is_enabled) { + dhcp_start((struct netif*)netdev->user_data); + } else { + dhcp_stop((struct netif*)netdev->user_data); + } + + return ERR_OK; +} +#endif + +static int lwip_netdev_set_default(struct netdev* netdev) +{ + netif_set_default((struct netif*)netdev->user_data); + return ERR_OK; +} + +static const struct netdev_ops lwip_netdev_ops = { + .set_up = lwip_netdev_set_up, + .set_down = lwip_netdev_set_down, + .set_addr_info = lwip_netdev_set_addr_info, +#ifdef LWIP_DNS + .set_dns_server = lwip_netdev_set_dns_server, +#endif +#ifdef LWIP_DHCP + .set_dhcp = lwip_netdev_set_dhcp, +#endif + .set_default = lwip_netdev_set_default, +}; + +static inline int netdev_set_flags(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + struct netdev* netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == NULL) { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + // set flags + if (lwip_netif->flags | NETIF_FLAG_BROADCAST) { + netdev->flags |= NETDEV_FLAG_BROADCAST; + } + if (lwip_netif->flags | NETIF_FLAG_ETHARP) { + netdev->flags |= NETDEV_FLAG_ETHARP; + } + if (lwip_netif->flags | NETIF_FLAG_IGMP) { + netdev->flags |= NETDEV_FLAG_IGMP; + } +#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */ + if (lwip_netif->flags & NETIF_FLAG_MLD6) { + netdev->flags |= NETDEV_FLAG_MLD6; + } +#endif /* LWIP_VERSION_MAJOR >= 2U */ + +#if LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, true); +#else + netdev_low_level_set_dhcp_status(netdev, false); +#endif + + return ERR_OK; +} + +int lwip_netdev_add(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + + struct netdev* netdev = calloc(1, sizeof(struct netdev)); + if (netdev == NULL) { + return -ERR_IF; + } + + // init netdev + char netif_name[NETIF_NAME_LEN + 1]; + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name)); + strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN); + // register netdev + int result = netdev_register(netdev, netif_name, (void*)lwip_netif); + // set values of netdev + netdev_set_flags(lwip_netif); + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + + return result; +} + +void lwip_netdev_del(struct netif* lwip_netif) +{ + char name[NETIF_NAME_LEN + 1]; + struct netdev* netdev; + + CHECK(lwip_netif); + + strncpy(name, lwip_netif->name, NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + free(netdev); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/connect_ethernet.h index 12f65358b..0933eecd5 100755 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/connect_ethernet.h @@ -33,6 +33,8 @@ #define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk) #endif +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); #ifdef __cplusplus } diff --git a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/enet_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/enet_ethernetif.h index 6c552e28c..e8fb06718 100644 --- a/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/enet_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/imxrt1176-sbc/third_party_driver/include/enet_ethernetif.h @@ -164,6 +164,9 @@ void ethernetif_input( void *netif_arg); int ETH_BSP_Config(void); void *ethernetif_config_enet_set(uint8_t enet_port); +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); + #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/Makefile index 14be72829..57c50e98b 100755 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c +SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c SRC_DIR := ksz8081 include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c index 9b8ca475a..114f1ef61 100755 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/enet_ethernetif.c @@ -68,6 +68,7 @@ #include "fsl_gpio.h" #include "fsl_iomuxc.h" +#include "netdev.h" #include "sys_arch.h" /******************************************************************************* @@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif, } #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__)); + if (EOK != lwip_netdev_add(netif)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__)); + } else { + printf("[%s] Add Netdev successful\n", __func__); + } return ERR_OK; } diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c new file mode 100644 index 000000000..03ca27594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/ethernet/eth_netdev.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/** +* @file eth_netdev.c +* @brief register net dev function for lwip +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +#include +#include +#include +#include +#include +#include + +static const uint32_t NETIF_NAME_LEN = 2; + +static int lwip_netdev_set_up(struct netdev* netdev) +{ + netif_set_up((struct netif*)netdev->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev* netif) +{ + netif_set_down((struct netif*)netif->user_data); + return ERR_OK; +} + +#ifndef ip_2_ip4 +#define ip_2_ip4(ipaddr) (ipaddr) +#endif +static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw) +{ + if (ip_addr && netmask && gw) { + netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } else { + if (ip_addr) { + netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr)); + } + if (netmask) { + netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask)); + } + if (gw) { + netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); + } + } +} + +#ifdef LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server) +{ +#if LWIP_VERSION_MAJOR == 1U /* v1.x */ + extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver); +#else /* >=2.x */ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server); +#endif /* LWIP_VERSION_MAJOR == 1U */ + + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif + +#ifdef LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) +{ + netdev_low_level_set_dhcp_status(netdev, is_enabled); + + if (true == is_enabled) { + dhcp_start((struct netif*)netdev->user_data); + } else { + dhcp_stop((struct netif*)netdev->user_data); + } + + return ERR_OK; +} +#endif + +static int lwip_netdev_set_default(struct netdev* netdev) +{ + netif_set_default((struct netif*)netdev->user_data); + return ERR_OK; +} + +static const struct netdev_ops lwip_netdev_ops = { + .set_up = lwip_netdev_set_up, + .set_down = lwip_netdev_set_down, + .set_addr_info = lwip_netdev_set_addr_info, +#ifdef LWIP_DNS + .set_dns_server = lwip_netdev_set_dns_server, +#endif +#ifdef LWIP_DHCP + .set_dhcp = lwip_netdev_set_dhcp, +#endif + .set_default = lwip_netdev_set_default, +}; + +static inline int netdev_set_flags(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + struct netdev* netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == NULL) { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + // set flags + if (lwip_netif->flags | NETIF_FLAG_BROADCAST) { + netdev->flags |= NETDEV_FLAG_BROADCAST; + } + if (lwip_netif->flags | NETIF_FLAG_ETHARP) { + netdev->flags |= NETDEV_FLAG_ETHARP; + } + if (lwip_netif->flags | NETIF_FLAG_IGMP) { + netdev->flags |= NETDEV_FLAG_IGMP; + } +#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */ + if (lwip_netif->flags & NETIF_FLAG_MLD6) { + netdev->flags |= NETDEV_FLAG_MLD6; + } +#endif /* LWIP_VERSION_MAJOR >= 2U */ + +#if LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, true); +#else + netdev_low_level_set_dhcp_status(netdev, false); +#endif + + return ERR_OK; +} + +int lwip_netdev_add(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + + struct netdev* netdev = calloc(1, sizeof(struct netdev)); + if (netdev == NULL) { + return -ERR_IF; + } + + // init netdev + char netif_name[NETIF_NAME_LEN + 1]; + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name)); + strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN); + // register netdev + int result = netdev_register(netdev, netif_name, (void*)lwip_netif); + // set values of netdev + netdev_set_flags(lwip_netif); + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + + return result; +} + +void lwip_netdev_del(struct netif* lwip_netif) +{ + char name[NETIF_NAME_LEN + 1]; + struct netdev* netdev; + + CHECK(lwip_netif); + + strncpy(name, lwip_netif->name, NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + free(netdev); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/connect_ethernet.h index 12f65358b..0933eecd5 100755 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/connect_ethernet.h @@ -33,6 +33,8 @@ #define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk) #endif +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); #ifdef __cplusplus } diff --git a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/enet_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/enet_ethernetif.h index 7b8c20c95..889b50acb 100755 --- a/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/enet_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/ok1052-c/third_party_driver/include/enet_ethernetif.h @@ -181,11 +181,14 @@ err_t ethernetif1_init(struct netif *netif); */ void ethernetif_input( void *netif_arg); -void ETH_BSP_Config(void); +int ETH_BSP_Config(void); void *ethernetif_config_enet_set(uint8_t enet_port); int32 lwip_obtain_semaphore(struct netif *netif); +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); + #define NETIF_ENET0_INIT_FUNC ethernetif0_init #if defined(__cplusplus) diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/Makefile index 65f5adc78..6cd8a10fa 100755 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c +SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c SRC_DIR := lan8720 include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c index 9b8ca475a..114f1ef61 100755 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/enet_ethernetif.c @@ -68,6 +68,7 @@ #include "fsl_gpio.h" #include "fsl_iomuxc.h" +#include "netdev.h" #include "sys_arch.h" /******************************************************************************* @@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif, } #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__)); + if (EOK != lwip_netdev_add(netif)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__)); + } else { + printf("[%s] Add Netdev successful\n", __func__); + } return ERR_OK; } diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c new file mode 100644 index 000000000..03ca27594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/ethernet/eth_netdev.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/** +* @file eth_netdev.c +* @brief register net dev function for lwip +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +#include +#include +#include +#include +#include +#include + +static const uint32_t NETIF_NAME_LEN = 2; + +static int lwip_netdev_set_up(struct netdev* netdev) +{ + netif_set_up((struct netif*)netdev->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev* netif) +{ + netif_set_down((struct netif*)netif->user_data); + return ERR_OK; +} + +#ifndef ip_2_ip4 +#define ip_2_ip4(ipaddr) (ipaddr) +#endif +static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw) +{ + if (ip_addr && netmask && gw) { + netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } else { + if (ip_addr) { + netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr)); + } + if (netmask) { + netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask)); + } + if (gw) { + netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); + } + } +} + +#ifdef LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server) +{ +#if LWIP_VERSION_MAJOR == 1U /* v1.x */ + extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver); +#else /* >=2.x */ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server); +#endif /* LWIP_VERSION_MAJOR == 1U */ + + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif + +#ifdef LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) +{ + netdev_low_level_set_dhcp_status(netdev, is_enabled); + + if (true == is_enabled) { + dhcp_start((struct netif*)netdev->user_data); + } else { + dhcp_stop((struct netif*)netdev->user_data); + } + + return ERR_OK; +} +#endif + +static int lwip_netdev_set_default(struct netdev* netdev) +{ + netif_set_default((struct netif*)netdev->user_data); + return ERR_OK; +} + +static const struct netdev_ops lwip_netdev_ops = { + .set_up = lwip_netdev_set_up, + .set_down = lwip_netdev_set_down, + .set_addr_info = lwip_netdev_set_addr_info, +#ifdef LWIP_DNS + .set_dns_server = lwip_netdev_set_dns_server, +#endif +#ifdef LWIP_DHCP + .set_dhcp = lwip_netdev_set_dhcp, +#endif + .set_default = lwip_netdev_set_default, +}; + +static inline int netdev_set_flags(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + struct netdev* netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == NULL) { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + // set flags + if (lwip_netif->flags | NETIF_FLAG_BROADCAST) { + netdev->flags |= NETDEV_FLAG_BROADCAST; + } + if (lwip_netif->flags | NETIF_FLAG_ETHARP) { + netdev->flags |= NETDEV_FLAG_ETHARP; + } + if (lwip_netif->flags | NETIF_FLAG_IGMP) { + netdev->flags |= NETDEV_FLAG_IGMP; + } +#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */ + if (lwip_netif->flags & NETIF_FLAG_MLD6) { + netdev->flags |= NETDEV_FLAG_MLD6; + } +#endif /* LWIP_VERSION_MAJOR >= 2U */ + +#if LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, true); +#else + netdev_low_level_set_dhcp_status(netdev, false); +#endif + + return ERR_OK; +} + +int lwip_netdev_add(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + + struct netdev* netdev = calloc(1, sizeof(struct netdev)); + if (netdev == NULL) { + return -ERR_IF; + } + + // init netdev + char netif_name[NETIF_NAME_LEN + 1]; + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name)); + strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN); + // register netdev + int result = netdev_register(netdev, netif_name, (void*)lwip_netif); + // set values of netdev + netdev_set_flags(lwip_netif); + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + + return result; +} + +void lwip_netdev_del(struct netif* lwip_netif) +{ + char name[NETIF_NAME_LEN + 1]; + struct netdev* netdev; + + CHECK(lwip_netif); + + strncpy(name, lwip_netif->name, NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + free(netdev); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/connect_ethernet.h index 12f65358b..0933eecd5 100755 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/connect_ethernet.h @@ -33,6 +33,8 @@ #define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk) #endif +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); #ifdef __cplusplus } diff --git a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/enet_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/enet_ethernetif.h index 7978b36b6..e6f59df3e 100755 --- a/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/enet_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/xidatong-arm32/third_party_driver/include/enet_ethernetif.h @@ -185,6 +185,9 @@ int ETH_BSP_Config(void); void *ethernetif_config_enet_set(uint8_t enet_port); int32 lwip_obtain_semaphore(struct netif *netif); +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); + #define NETIF_ENET0_INIT_FUNC ethernetif0_init #if defined(__cplusplus) diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/Makefile index 65f5adc78..6cd8a10fa 100755 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c +SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c SRC_DIR := lan8720 include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c index 9b8ca475a..114f1ef61 100755 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/enet_ethernetif.c @@ -68,6 +68,7 @@ #include "fsl_gpio.h" #include "fsl_iomuxc.h" +#include "netdev.h" #include "sys_arch.h" /******************************************************************************* @@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif, } #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__)); + if (EOK != lwip_netdev_add(netif)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__)); + } else { + printf("[%s] Add Netdev successful\n", __func__); + } return ERR_OK; } diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c new file mode 100644 index 000000000..03ca27594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/ethernet/eth_netdev.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + */ + +/** +* @file eth_netdev.c +* @brief register net dev function for lwip +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +#include +#include +#include +#include +#include +#include + +static const uint32_t NETIF_NAME_LEN = 2; + +static int lwip_netdev_set_up(struct netdev* netdev) +{ + netif_set_up((struct netif*)netdev->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev* netif) +{ + netif_set_down((struct netif*)netif->user_data); + return ERR_OK; +} + +#ifndef ip_2_ip4 +#define ip_2_ip4(ipaddr) (ipaddr) +#endif +static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw) +{ + if (ip_addr && netmask && gw) { + netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } else { + if (ip_addr) { + netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr)); + } + if (netmask) { + netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask)); + } + if (gw) { + netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw)); + } + } +} + +#ifdef LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server) +{ +#if LWIP_VERSION_MAJOR == 1U /* v1.x */ + extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver); +#else /* >=2.x */ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server); +#endif /* LWIP_VERSION_MAJOR == 1U */ + + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif + +#ifdef LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled) +{ + netdev_low_level_set_dhcp_status(netdev, is_enabled); + + if (true == is_enabled) { + dhcp_start((struct netif*)netdev->user_data); + } else { + dhcp_stop((struct netif*)netdev->user_data); + } + + return ERR_OK; +} +#endif + +static int lwip_netdev_set_default(struct netdev* netdev) +{ + netif_set_default((struct netif*)netdev->user_data); + return ERR_OK; +} + +static const struct netdev_ops lwip_netdev_ops = { + .set_up = lwip_netdev_set_up, + .set_down = lwip_netdev_set_down, + .set_addr_info = lwip_netdev_set_addr_info, +#ifdef LWIP_DNS + .set_dns_server = lwip_netdev_set_dns_server, +#endif +#ifdef LWIP_DHCP + .set_dhcp = lwip_netdev_set_dhcp, +#endif + .set_default = lwip_netdev_set_default, +}; + +static inline int netdev_set_flags(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + struct netdev* netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == NULL) { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + // set flags + if (lwip_netif->flags | NETIF_FLAG_BROADCAST) { + netdev->flags |= NETDEV_FLAG_BROADCAST; + } + if (lwip_netif->flags | NETIF_FLAG_ETHARP) { + netdev->flags |= NETDEV_FLAG_ETHARP; + } + if (lwip_netif->flags | NETIF_FLAG_IGMP) { + netdev->flags |= NETDEV_FLAG_IGMP; + } +#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */ + if (lwip_netif->flags & NETIF_FLAG_MLD6) { + netdev->flags |= NETDEV_FLAG_MLD6; + } +#endif /* LWIP_VERSION_MAJOR >= 2U */ + +#if LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, true); +#else + netdev_low_level_set_dhcp_status(netdev, false); +#endif + + return ERR_OK; +} + +int lwip_netdev_add(struct netif* lwip_netif) +{ + CHECK(lwip_netif); + + struct netdev* netdev = calloc(1, sizeof(struct netdev)); + if (netdev == NULL) { + return -ERR_IF; + } + + // init netdev + char netif_name[NETIF_NAME_LEN + 1]; + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name)); + strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN); + // register netdev + int result = netdev_register(netdev, netif_name, (void*)lwip_netif); + // set values of netdev + netdev_set_flags(lwip_netif); + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + + return result; +} + +void lwip_netdev_del(struct netif* lwip_netif) +{ + char name[NETIF_NAME_LEN + 1]; + struct netdev* netdev; + + CHECK(lwip_netif); + + strncpy(name, lwip_netif->name, NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + free(netdev); +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/connect_ethernet.h b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/connect_ethernet.h index 49f92d4c8..360b28125 100755 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/connect_ethernet.h +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/connect_ethernet.h @@ -1,22 +1,22 @@ /* -* Copyright (c) 2021 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. -*/ + * Copyright (c) 2021 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 connect_ethernet.h -* @brief Adapted network software protocol stack and hardware operation functions -* @version 1.0 -* @author AIIT XUOS Lab -* @date 2021-12-7 -*/ + * @file connect_ethernet.h + * @brief Adapted network software protocol stack and hardware operation functions + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021-12-7 + */ #ifndef __CONNECT_ETHERNET_H_ #define __CONNECT_ETHERNET_H_ @@ -25,17 +25,18 @@ #include "enet_ethernetif_priv.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif #ifndef sourceClock #define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk) #endif +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); #ifdef __cplusplus } #endif #endif - diff --git a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/enet_ethernetif.h b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/enet_ethernetif.h index 7978b36b6..e6f59df3e 100755 --- a/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/enet_ethernetif.h +++ b/Ubiquitous/XiZi_IIoT/board/xiwangtong-arm32/third_party_driver/include/enet_ethernetif.h @@ -185,6 +185,9 @@ int ETH_BSP_Config(void); void *ethernetif_config_enet_set(uint8_t enet_port); int32 lwip_obtain_semaphore(struct netif *netif); +int lwip_netdev_add(struct netif* lwip_netif); +void lwip_netdev_del(struct netif* lwip_netif); + #define NETIF_ENET0_INIT_FUNC ethernetif0_init #if defined(__cplusplus) diff --git a/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c b/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c index e340d08fe..d81b9113a 100644 --- a/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c +++ b/Ubiquitous/XiZi_IIoT/fs/shared/src/iot-vfs.c @@ -772,7 +772,8 @@ int stat(const char *path, struct stat *buf) ret = mp->fs->stat(mp, relpath, &vfs_statbuf); if (ret < 0) { - SYS_ERR("%s: stat file failed\n", __func__); + // stat() is absolutely fine to check if a file exists + // SYS_ERR("%s: stat file failed\n", __func__); goto err; } @@ -790,7 +791,6 @@ err: free(abspath); if (ret < 0) { - KUpdateExstatus(ret); return -1; } return 0; diff --git a/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h b/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h index dcb75cee8..7dc4bc7fa 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h +++ b/Ubiquitous/XiZi_IIoT/kernel/include/xs_kdbg.h @@ -1,23 +1,23 @@ /* -* Copyright (c) 2020 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. -*/ + * Copyright (c) 2020 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: xs_kdbg.h -* @brief: function declaration and structure defintion of kernel debug -* @version: 1.0 -* @author: AIIT XUOS Lab -* @date: 2020/4/20 -* -*/ + * @file: xs_kdbg.h + * @brief: function declaration and structure defintion of kernel debug + * @version: 1.0 + * @author: AIIT XUOS Lab + * @date: 2020/4/20 + * + */ #ifndef XS_KDBG_H #define XS_KDBG_H @@ -28,6 +28,8 @@ extern "C" { #endif +#define KERNEL_DEBUG + #ifdef KERNEL_DEBUG /*Kernel Section Debug Define*/ @@ -40,18 +42,22 @@ extern "C" { #define KDBG_IPC 0 #define KDBG_HOOK 0 -#define SYS_KDEBUG_LOG(section, information) \ - do \ - { \ - if(section) { \ - KPrintf information; \ - } \ - }while (0) +#define MSGQUEUE_DEBUG 0 +#define FILESYS_DEBUG 0 +#define NETDEV_DEBUG 0 +#define WEBNET_DEBUG 0 -#define KDYN_NONE 0 -#define KDYN_DBG 1 -#define KDYN_ERROR 2 -#define KDYN_WARNING 3 +#define SYS_KDEBUG_LOG(section, information) \ + do { \ + if (section) { \ + KPrintf information; \ + } \ + } while (0) + +#define KDYN_NONE 0 +#define KDYN_DBG 1 +#define KDYN_ERROR 2 +#define KDYN_WARNING 3 #ifdef KDYN_LOG_DBG #define DBG(args, ...) KDYNAMIC_LOG(KDYN_DBG, args, ##__VA_ARGS__) @@ -63,83 +69,76 @@ extern "C" { #define SYS_WARN(args, ...) KDYNAMIC_LOG(KDYN_WARNING, args, ##__VA_ARGS__) #endif -#define KDYNAMIC_LOG(level, args, ...) \ - do \ - { \ - switch(level) \ - { \ - case KDYN_NONE: \ - break; \ - case KDYN_DBG: \ - KPrintf("[DBG]"); \ - KPrintf(args, ##__VA_ARGS__); \ - break; \ - case KDYN_ERROR: \ - KPrintf("[ERR]"); \ - KPrintf(args, ##__VA_ARGS__); \ - break; \ - case KDYN_WARNING: \ - KPrintf("[WARN]"); \ - KPrintf(args, ##__VA_ARGS__); \ - break; \ - default: \ - break; \ - } \ - }while (0) +#define KDYNAMIC_LOG(level, args, ...) \ + do { \ + switch (level) { \ + case KDYN_NONE: \ + break; \ + case KDYN_DBG: \ + KPrintf("[DBG]"); \ + KPrintf(args, ##__VA_ARGS__); \ + break; \ + case KDYN_ERROR: \ + KPrintf("[ERR]"); \ + KPrintf(args, ##__VA_ARGS__); \ + break; \ + case KDYN_WARNING: \ + KPrintf("[WARN]"); \ + KPrintf(args, ##__VA_ARGS__); \ + break; \ + default: \ + break; \ + } \ + } while (0) -#define NULL_PARAM_CHECK(param) \ - do \ - { \ - if(param == NONE) { \ - KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \ - while(RET_TRUE); \ - } \ - }while (0) +#define NULL_PARAM_CHECK(param) \ + do { \ + if (param == NONE) { \ + KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n", __FUNCTION__, __LINE__, #param); \ + while (RET_TRUE) \ + ; \ + } \ + } while (0) -#define CHECK(TRUE_CONDITION) \ - do \ - { \ - if(!(TRUE_CONDITION)) { \ - KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n",#TRUE_CONDITION,__LINE__,__FUNCTION__);\ - while(RET_TRUE); \ - } \ - } while(0) +#define CHECK(TRUE_CONDITION) \ + do { \ + if (!(TRUE_CONDITION)) { \ + KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n", #TRUE_CONDITION, __LINE__, __FUNCTION__); \ + while (RET_TRUE) \ + ; \ + } \ + } while (0) +#define KDEBUG_NOT_IN_INTERRUPT \ + do { \ + x_base level; \ + level = DISABLE_INTERRUPT(); \ + if (isrManager.done->getCounter() != 0) { \ + KPrintf("Function[%s] is not supported in ISR\n", __FUNCTION__); \ + CHECK(0); \ + } \ + ENABLE_INTERRUPT(level); \ + } while (0) -#define KDEBUG_NOT_IN_INTERRUPT \ - do \ - { \ - x_base level; \ - level = DISABLE_INTERRUPT(); \ - if (isrManager.done->getCounter() != 0) \ - { \ - KPrintf("Function[%s] is not supported in ISR\n", __FUNCTION__); \ - CHECK(0); \ - } \ - ENABLE_INTERRUPT(level); \ - } while (0) +#define KDEBUG_IN_KTASK_CONTEXT \ + do { \ + x_base level; \ + level = DISABLE_INTERRUPT(); \ + if (GetKTaskDescriptor() == NONE) { \ + KPrintf("Function[%s] is not supported before task assign\n", __FUNCTION__); \ + CHECK(0); \ + } \ + KDEBUG_NOT_IN_INTERRUPT; \ + ENABLE_INTERRUPT(level); \ + } while (0) -#define KDEBUG_IN_KTASK_CONTEXT \ - do \ - { \ - x_base level; \ - level = DISABLE_INTERRUPT(); \ - if (GetKTaskDescriptor() == NONE) \ - { \ - KPrintf("Function[%s] is not supported before task assign\n", __FUNCTION__); \ - CHECK(0); \ - } \ - KDEBUG_NOT_IN_INTERRUPT; \ - ENABLE_INTERRUPT(level); \ - } while (0) - -#define NOT_IN_CRITICAL_AREA \ - do { \ - if(GetOsAssignLockLevel() != 0){ \ +#define NOT_IN_CRITICAL_AREA \ + do { \ + if (GetOsAssignLockLevel() != 0) { \ KPrintf("Function[%s] is not supported switch in critical area.\n", __FUNCTION__); \ - CHECK(0); \ - } \ - } while (0) + CHECK(0); \ + } \ + } while (0) #else @@ -159,4 +158,4 @@ extern "C" { } #endif -#endif +#endif diff --git a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_i2c.c b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_i2c.c index cd41074bf..37a3c39ff 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_i2c.c +++ b/Ubiquitous/XiZi_IIoT/kernel/kernel_test/test_i2c.c @@ -35,6 +35,7 @@ #define ADDR 0x44 /* slave address */ static struct Bus *i2c_bus = NONE; /* I2C bus handle */ +static char addr = 0x44; typedef struct Hs300xData { @@ -50,6 +51,9 @@ static x_err_t WriteReg(struct HardwareDev *dev) { struct BusBlockWriteParam write_param; + write_param.buffer = &addr; + write_param.size = 1; + /* use I2C device API transfer data */ if(1 == BusDevWriteData(dev, &write_param)) { return EOK; diff --git a/Ubiquitous/XiZi_IIoT/kernel/memory/byte_manage.c b/Ubiquitous/XiZi_IIoT/kernel/memory/byte_manage.c index 1536fedc2..3bf3144cb 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/memory/byte_manage.c +++ b/Ubiquitous/XiZi_IIoT/kernel/memory/byte_manage.c @@ -53,8 +53,10 @@ #define ALLOC_BLOCK_MASK 0xc0000000 #define DYNAMIC_REMAINING_MASK 0x3fffffff -#define SIZEOF_32B (32) -#define SIZEOF_64B (64) +enum SmallSizeAllocSize { + SIZEOF_32B = 32, + SIZEOF_64B = 64, +}; #define SMALL_SIZE_32B(ITEMSIZE) ((ITEMSIZE + SIZEOF_DYNAMICALLOCNODE_MEM) * SMALL_NUMBER_32B) /* Calculate the total size for SIZEOF_32B blocks*/ #define SMALL_SIZE_64B(ITEMSIZE) ((ITEMSIZE + SIZEOF_DYNAMICALLOCNODE_MEM) * SMALL_NUMBER_64B) /* Calculate the total size for SIZEOF_64B blocks*/ @@ -143,7 +145,7 @@ struct ByteMemory struct StaticMemoryDone { void (*init)(struct ByteMemory *byte_memory); - void* (*malloc)(struct ByteMemory *byte_memory, x_size_t size); + void* (*malloc)(struct ByteMemory *byte_memory, enum SmallSizeAllocSize size); void (*release)(void *pointer); }; @@ -182,7 +184,7 @@ static int JudgeValidAddressRange(struct DynamicBuddyMemory *dynamic_buddy, void NULL_PARAM_CHECK(pointer); /* the given address is between the physical start address and physical end address */ - if(((struct DynamicAllocNode *)pointer > dynamic_buddy->mm_dynamic_start[0]) && ((struct DynamicAllocNode *)pointer < dynamic_buddy->mm_dynamic_end[0])) { + if (((struct DynamicAllocNode *)pointer > dynamic_buddy->mm_dynamic_start[0]) && ((struct DynamicAllocNode *)pointer < dynamic_buddy->mm_dynamic_end[0])) { return RET_TRUE; } /* invalid address */ @@ -349,11 +351,18 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz } /* best-fit method */ - for (node = dynamic_buddy->mm_freenode_list[ndx].next; - (ndx < MEM_LINKNRS ) && (node->size < allocsize); - node = node->next) { - ndx++; - }; + node = dynamic_buddy->mm_freenode_list[ndx].next; + while(ndx < MEM_LINKNRS && (NONE == node || node->size < allocsize)) { + if (NONE == node) { + ndx++; + if (ndx == MEM_LINKNRS) { // no space to allocate + return NONE; + } + node = dynamic_buddy->mm_freenode_list[ndx].next; + } else { + node = node->next; + } + } /* get the best-fit freeNode */ if (node && (node->size >= allocsize)) { struct DynamicFreeNode *remainder; @@ -371,7 +380,7 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz /* create the remainder node */ remainder = PTR2FREENODE(((char *)node) + allocsize); - remainder->size = remaining; + remainder->size = remaining; remainder->prev_adj_size = allocsize; remainder->flag = 0; @@ -385,13 +394,12 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz } /* handle the case of an exact size match */ - node->flag = extsram_mask; result = (void *)((char *)node + SIZEOF_DYNAMICALLOCNODE_MEM); } /* failure allocation */ - if(result == NONE) { + if (result == NONE) { #ifndef MEM_EXTERN_SRAM KPrintf("%s: allocation failed, size %d.\n", __func__, size); #endif @@ -429,9 +437,9 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer) byte_memory->dynamic_buddy_manager.active_memory -= node->size; #endif /* get the next sibling freeNode */ - next = PTR2FREENODE((char*)node+node->size); + next = PTR2FREENODE((char*)node + node->size); - if(((next->flag & DYNAMIC_BLOCK_MASK) == 0)) { + if (((next->flag & DYNAMIC_BLOCK_MASK) == 0)) { struct DynamicAllocNode *andbeyond; andbeyond = PTR2ALLOCNODE((char*)next + next->size); @@ -446,7 +454,7 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer) } /* get the prev sibling freeNode */ prev = (struct DynamicFreeNode*)((char*)node - node->prev_adj_size ); - if((prev->flag & DYNAMIC_BLOCK_MASK)==0) { + if ((prev->flag & DYNAMIC_BLOCK_MASK) == 0) { prev->prev->next=prev->next; if(prev->next){ @@ -459,7 +467,7 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer) node->flag = 0; /* insert freeNode into dynamic buddy memory */ - AddNewNodeIntoBuddy(&byte_memory->dynamic_buddy_manager,node); + AddNewNodeIntoBuddy(&byte_memory->dynamic_buddy_manager, node); } static struct DynamicBuddyMemoryDone DynamicDone = { @@ -545,12 +553,14 @@ static void SmallMemFree(void *pointer) NULL_PARAM_CHECK(pointer); /* get the allocNode */ - node = PTR2ALLOCNODE((char*)pointer-SIZEOF_DYNAMICALLOCNODE_MEM); + node = PTR2ALLOCNODE((char*)pointer - SIZEOF_DYNAMICALLOCNODE_MEM); static_segment = (struct segment*)(x_size_t)node->size; /* update the statistic information of static_segment */ node->size = (x_size_t)static_segment->freelist; static_segment->freelist = (uint8 *)node; + node->flag = 0; // it's unnecessary, actually + static_segment->block_free_count++; /* parameter detection */ @@ -565,7 +575,7 @@ static void SmallMemFree(void *pointer) * * @return pointer address on success; NULL on failure */ -static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size) +static void *SmallMemMalloc(struct ByteMemory *byte_memory, enum SmallSizeAllocSize size) { uint8 i = 0; void *result = NONE; @@ -580,7 +590,7 @@ static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size) static_segment = &byte_memory->static_manager[1]; /* current static segment has free static memory block */ - if(static_segment->block_free_count>0) { + if(static_segment->block_free_count > 0) { /* get the head static memory block */ result = static_segment->freelist; node = PTR2ALLOCNODE(static_segment->freelist); @@ -592,27 +602,14 @@ static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size) node->size = (long)static_segment; } - if(result) { + if (NONE != result) { /* return static memory block */ return (char*)result + SIZEOF_DYNAMICALLOCNODE_MEM; } /* the static memory block is exhausted, now turn to dynamic buddy memory for allocation. */ - result = byte_memory->dynamic_buddy_manager.done->malloc(&byte_memory->dynamic_buddy_manager, size, DYNAMIC_BLOCK_NO_EXTMEM_MASK); -#ifdef MEM_EXTERN_SRAM - if(NONE == result) { - for(i = 0; i < EXTSRAM_MAX_NUM; i++) { - if(NONE != ExtByteManager[i].done) { - result = ExtByteManager[i].dynamic_buddy_manager.done->malloc(&ExtByteManager[i].dynamic_buddy_manager, size, DYNAMIC_BLOCK_EXTMEMn_MASK(i + 1)); - if (result){ - CHECK(ExtByteManager[i].dynamic_buddy_manager.done->JudgeLegal(&ExtByteManager[i].dynamic_buddy_manager, ret - SIZEOF_DYNAMICALLOCNODE_MEM)); - break; - } - } - } - } -#endif - return result; + // fall to dynamic allocation + return NONE; } static struct StaticMemoryDone StaticDone = { @@ -634,41 +631,46 @@ void *x_malloc(x_size_t size) void *ret = NONE; register x_base lock = 0; - /* parameter detection */ + /* hold lock before allocation */ + lock = CriticalAreaLock(); + /* alignment */ + size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE); + + /* parameter detection */ #ifdef MEM_EXTERN_SRAM /* parameter detection */ if(size == 0 ){ - return NONE; + CriticalAreaUnLock(lock); + return NONE; } if((size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory)){ - lock = CriticalAreaLock(); /* alignment */ size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE); goto try_extmem; } - #else - /* parameter detection */ - if((size == 0) || (size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory)) + /* parameter detection */ + if((size == 0) || (size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory)) { + CriticalAreaUnLock(lock); return NONE; + } #endif - /* hold lock before allocation */ - lock = CriticalAreaLock(); - /* alignment */ - size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE); + /* determine allocation operation from static segments or dynamic buddy memory */ #ifdef KERNEL_SMALL_MEM_ALLOC if(size <= SIZEOF_32B) { - ret = ByteManager.static_manager[0].done->malloc(&ByteManager,SIZEOF_32B); - } else if(size <= SIZEOF_64B) { - ret = ByteManager.static_manager[1].done->malloc(&ByteManager,SIZEOF_64B); - } else + ret = ByteManager.static_manager[0].done->malloc(&ByteManager, SIZEOF_32B); + } else if (size <= SIZEOF_64B) { + ret = ByteManager.static_manager[1].done->malloc(&ByteManager, SIZEOF_64B); + } #endif - { + + if (ret == NONE) { ret = ByteManager.dynamic_buddy_manager.done->malloc(&ByteManager.dynamic_buddy_manager, size, DYNAMIC_BLOCK_NO_EXTMEM_MASK); - if(ret != NONE) + if (ret != NONE) { CHECK(ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager, ret - SIZEOF_DYNAMICALLOCNODE_MEM)); + } #ifdef MEM_EXTERN_SRAM try_extmem: @@ -686,6 +688,7 @@ try_extmem: } #endif } + /* release lock */ CriticalAreaUnLock(lock); return ret; @@ -781,14 +784,20 @@ void x_free(void *pointer) struct DynamicAllocNode *node = NONE; /* parameter detection */ - if (pointer == NONE) - return ; - - CHECK(ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager,pointer)); + if (pointer == NONE) { + return; + } /* hold lock before release */ lock = CriticalAreaLock(); - node = PTR2ALLOCNODE((char*)pointer-SIZEOF_DYNAMICALLOCNODE_MEM); + + if (!ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager, pointer)) { + CriticalAreaUnLock(lock); + SYS_ERR("[%s] Freeing a unallocated address.\n", __func__); + return; + } + + node = PTR2ALLOCNODE((char*)pointer - SIZEOF_DYNAMICALLOCNODE_MEM); CHECK(ByteManager.done->JudgeAllocated(node)); /* judge release the memory block ro static_segment or dynamic buddy memory */ @@ -799,19 +808,20 @@ void x_free(void *pointer) #endif { #ifdef MEM_EXTERN_SRAM - /* judge the pointer is not malloced from extern memory*/ - if(0 == (node->flag & 0xFF0000)) { - ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer); - } + /* judge the pointer is not malloced from extern memory*/ + if(0 == (node->flag & 0xFF0000)) { + ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer); + } - /* judge the pointer is malloced from extern memory*/ - if(0 != (node->flag & 0xFF0000)) { - ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1].dynamic_buddy_manager.done->release(&ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1],pointer); - } + /* judge the pointer is malloced from extern memory*/ + if(0 != (node->flag & 0xFF0000)) { + ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1].dynamic_buddy_manager.done->release(&ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1],pointer); + } #else - ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer); + ByteManager.dynamic_buddy_manager.done->release(&ByteManager, pointer); #endif } + /* release the lock */ CriticalAreaUnLock(lock); } @@ -888,7 +898,8 @@ void InitBoardMemory(void *start_phy_address, void *end_phy_address) /* parameter detection */ if (ByteManager.dynamic_buddy_manager.dynamic_buddy_start >= ByteManager.dynamic_buddy_manager.dynamic_buddy_end) { //KPrintf("InitBoardMemory, wrong address[0x%x - 0x%x]\n", (x_ubase)start_phy_address, (x_ubase)end_phy_address); - return; + SYS_KDEBUG_LOG(KDBG_MEM, ("InitBoardMemory, wrong address[0x%x - 0x%x]\n", (x_ubase)start_phy_address, (x_ubase)end_phy_address)); + return; } mheap->mm_total_size = 0; diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/delay.c b/Ubiquitous/XiZi_IIoT/kernel/thread/delay.c index 1cbdabaa4..6842ac209 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/delay.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/delay.c @@ -30,7 +30,7 @@ DoubleLinklistType xiaoshan_delay_head = {&xiaoshan_delay_head, &xiaoshan_delay_head}; /** - * This function will delay a task with sone ticks. + * This function will delay a task with some ticks. * * @param task the task needed to be delayed * @param ticks delay timeout diff --git a/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c b/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c index ee58bc0d7..526331aeb 100644 --- a/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c +++ b/Ubiquitous/XiZi_IIoT/kernel/thread/msgqueue.c @@ -21,6 +21,7 @@ #include #include +#include DECLARE_ID_MANAGER(k_mq_id_manager, ID_NUM_MAX); DoubleLinklistType k_mq_list = {&k_mq_list, &k_mq_list}; @@ -41,17 +42,17 @@ static struct MsgQueue *GetMsgQueueById(int32 id) lock = CriticalAreaLock(); idnode = IdGetObj(&k_mq_id_manager, id); - if (idnode == NONE){ - CriticalAreaUnLock(lock); - return NONE; + if (idnode == NONE) { + CriticalAreaUnLock(lock); + return NONE; } mq = CONTAINER_OF(idnode, struct MsgQueue, id); CriticalAreaUnLock(lock); + return mq; } -static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size, - x_size_t max_msgs ) +static x_err_t _InitMsgQueue(struct MsgQueue* mq, x_size_t msg_size, x_size_t max_msgs) { x_base lock = 0; @@ -62,10 +63,12 @@ static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size, mq->each_len = ALIGN_MEN_UP(msg_size, MEM_ALIGN_SIZE); mq->index = 0; + SYS_KDEBUG_LOG(MSGQUEUE_DEBUG, ("[%s] Msg attr, max_msg_num: %d, block size: %d\n", __func__, mq->max_msgs, mq->each_len)); + InitDoubleLinkList(&mq->send_pend_list); InitDoubleLinkList(&(mq->recv_pend_list)); - mq->msg_buf = x_malloc( mq->each_len * mq->max_msgs); + mq->msg_buf = x_malloc(mq->each_len * mq->max_msgs); if (mq->msg_buf == NONE) { lock = CriticalAreaLock(); DoubleLinkListRmNode(&(mq->link)); @@ -77,26 +80,28 @@ static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size, return EOK; } -static x_err_t _MsgQueueSend(struct MsgQueue *mq, - const void *buffer, - x_size_t size, - int32 msec) +static x_err_t _MsgQueueSend(struct MsgQueue* mq, + const void* buffer, + x_size_t size, + int32 msec) { x_ubase lock = 0; uint32 tick_delta = 0; int32 timeout = 0; - uint8 *msg = NONE; + uint8* msg = NONE; struct TaskDescriptor *task = NONE; NULL_PARAM_CHECK(mq); NULL_PARAM_CHECK(buffer); + SYS_KDEBUG_LOG(MSGQUEUE_DEBUG, ("[%s] mq_num_msgs: %d, block size: %d, needed size: %d\n", __func__, mq->num_msgs, mq->each_len, size)); + if (size > mq->each_len) return -ERROR; tick_delta = 0; task = GetKTaskDescriptor(); - if(WAITING_FOREVER == msec) + if (WAITING_FOREVER == msec) timeout = WAITING_FOREVER; else timeout = CalculateTickFromTimeMs(msec); @@ -107,8 +112,7 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq, return -EFULL; } - while(mq->num_msgs >= mq->max_msgs ) { - + while (mq->num_msgs >= mq->max_msgs) { task->exstatus = EOK; if (timeout == 0) { CriticalAreaUnLock(lock); @@ -121,7 +125,7 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq, tick_delta = CurrentTicksGain(); SYS_KDEBUG_LOG(KDBG_IPC, ("mq_send_wait: start timer of task:%s\n", task->task_base_info.name)); - KTaskSetDelay(task,timeout); + KTaskSetDelay(task, timeout); } CriticalAreaUnLock(lock); @@ -139,19 +143,19 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq, if (timeout < 0) timeout = 0; } - } + } // end with lock here - msg = mq->msg_buf + ( ( mq->index + mq->num_msgs ) % mq->max_msgs ) * mq->each_len ; + msg = mq->msg_buf + ((mq->index + mq->num_msgs) % mq->max_msgs) * mq->each_len; memcpy(msg, buffer, size); - mq->num_msgs ++; + mq->num_msgs++; if (!IsDoubleLinkListEmpty(&mq->recv_pend_list)) { LinklistResume(&(mq->recv_pend_list)); CriticalAreaUnLock(lock); DO_KTASK_ASSIGN; return EOK; } - CriticalAreaUnLock(lock); + return EOK; } @@ -191,15 +195,15 @@ static x_err_t _MsgQueueUrgentSend(struct MsgQueue *mq, const void *buffer, x_si return EOK; } -static x_err_t _MsgQueueRecv(struct MsgQueue *mq, - void *buffer, - x_size_t size, - int32 msec) +static x_err_t _MsgQueueRecv(struct MsgQueue* mq, + void* buffer, + x_size_t size, + int32 msec) { x_ubase lock = 0; uint32 tick_delta = 0; int32 timeout = 0; - struct MqMessage *msg = NONE; + uint8* msg = NONE; struct TaskDescriptor *task = NONE; NULL_PARAM_CHECK(mq); @@ -208,14 +212,14 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq, tick_delta = 0; task = GetKTaskDescriptor(); timeout = CalculateTickFromTimeMs(msec); - lock = CriticalAreaLock(); + lock = CriticalAreaLock(); if (mq->index == 0 && timeout == 0) { CriticalAreaUnLock(lock); return -ETIMEOUT; } - for( ; mq->num_msgs <= 0 ; ) { + while (mq->num_msgs <= 0) { KDEBUG_IN_KTASK_CONTEXT; task->exstatus = EOK; @@ -225,19 +229,16 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq, return -ETIMEOUT; } - LinklistSuspend(&(mq->recv_pend_list), - task, - LINKLIST_FLAG_FIFO); + LinklistSuspend(&(mq->recv_pend_list), task, LINKLIST_FLAG_FIFO); if (timeout > 0) { tick_delta = CurrentTicksGain(); SYS_KDEBUG_LOG(KDBG_IPC, ("set task:%s to timer list\n", task->task_base_info.name)); - KTaskSetDelay(task,timeout); + KTaskSetDelay(task, timeout); } CriticalAreaUnLock(lock); - DO_KTASK_ASSIGN; if (task->exstatus != EOK) { @@ -256,8 +257,8 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq, msg = mq->msg_buf + mq->index * mq->each_len; mq->index = (mq->index + 1) % mq->max_msgs; - memcpy(buffer, msg , size > mq->each_len ? mq->each_len : size); - mq->num_msgs --; + memcpy(buffer, msg, size > mq->each_len ? mq->each_len : size); + mq->num_msgs--; if (!IsDoubleLinkListEmpty(&(mq->send_pend_list))) { LinklistResume(&(mq->send_pend_list)); @@ -326,8 +327,7 @@ static struct MsgQueueDone Done = { * * @return id on success;ENOMEMORY/ERROR on failure */ -int32 KCreateMsgQueue(x_size_t msg_size, - x_size_t max_msgs) +int32 KCreateMsgQueue(x_size_t msg_size, x_size_t max_msgs) { int32 id = 0; x_base temp = 0; @@ -337,11 +337,12 @@ int32 KCreateMsgQueue(x_size_t msg_size, mq = (struct MsgQueue *)x_malloc(sizeof(struct MsgQueue)); if (mq == NONE) return -ENOMEMORY; - memset(mq,0x0,sizeof(struct MsgQueue)); + memset(mq, 0x0, sizeof(struct MsgQueue)); lock = CriticalAreaLock(); id = IdInsertObj(&k_mq_id_manager, &mq->id); CriticalAreaUnLock(lock); + if (id < 0) { x_free(mq); return -ENOMEMORY; @@ -350,11 +351,12 @@ int32 KCreateMsgQueue(x_size_t msg_size, lock = CriticalAreaLock(); DoubleLinkListInsertNodeAfter(&k_mq_list, &mq->link); CriticalAreaUnLock(lock); + mq->Done = &Done; - if( mq->Done->init(mq, msg_size,max_msgs) == EOK ) - return mq->id.id; + if (mq->Done->init(mq, msg_size, max_msgs) == EOK) + return mq->id.id; else - return -ERROR; + return -ERROR; } /** @@ -401,7 +403,7 @@ x_err_t KMsgQueueRecv(int32 id, mq = GetMsgQueueById(id); if (mq != NONE) - return mq->Done->recv(mq,buffer,size,timeout); + return mq->Done->recv(mq, buffer, size, timeout); else return -EINVALED; @@ -471,10 +473,11 @@ x_err_t KMsgQueueSend(int32 id, const void *buffer, x_size_t size) mq = GetMsgQueueById(id); if (mq != NONE) - return mq->Done->send(mq,buffer,size,0); + return mq->Done->send(mq, buffer, size, WAITING_FOREVER); else return -EINVALED; } + /** * send message with waiting time,current suspend task will be resumed * diff --git a/Ubiquitous/XiZi_IIoT/path_app.mk b/Ubiquitous/XiZi_IIoT/path_app.mk index 78427f764..a027e759a 100644 --- a/Ubiquitous/XiZi_IIoT/path_app.mk +++ b/Ubiquitous/XiZi_IIoT/path_app.mk @@ -8,6 +8,9 @@ ifeq ($(CONFIG_APP_SELECT_NEWLIB), y) APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/app_newlib/include # endif +ifeq ($(CONFIG_APP_USING_WEBNET),y) + APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/inc # +endif ifeq ($(CONFIG_ADD_XIZI_FEATURES), y) APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/transform_layer/xizi \ @@ -36,6 +39,7 @@ ifeq ($(CONFIG_CRYPTO), y) APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/security/crypto/include # endif + # COMPILE_APP: # @$(eval CPPPATHS=$(APPPATHS)) # @echo $(SRC_APP_DIR) diff --git a/Ubiquitous/XiZi_IIoT/path_kernel.mk b/Ubiquitous/XiZi_IIoT/path_kernel.mk index df84837ca..c32ee1572 100755 --- a/Ubiquitous/XiZi_IIoT/path_kernel.mk +++ b/Ubiquitous/XiZi_IIoT/path_kernel.mk @@ -52,6 +52,8 @@ KERNELPATHS += \ -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 @@ -86,6 +88,8 @@ KERNELPATHS += \ -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 @@ -334,6 +338,8 @@ KERNELPATHS += \ -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 @@ -365,6 +371,8 @@ KERNELPATHS += \ -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 @@ -419,6 +427,8 @@ KERNELPATHS += \ -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 @@ -554,9 +564,16 @@ endif endif +ifeq ($(CONFIG_APP_USING_WEBNET),y) + KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/inc \ + -I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/samples # +endif + + ifeq ($(CONFIG_TOOL_SHELL), y) KERNELPATHS +=-I$(KERNEL_ROOT)/tool/shell/letter-shell \ - -I$(KERNEL_ROOT)/tool/shell/letter-shell/file_ext # + -I$(KERNEL_ROOT)/tool/shell/letter-shell/file_ext \ + -I$(KERNEL_ROOT)/tool/shell/ endif ifeq ($(CONFIG_TOOL_USING_OTA), y) diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h index cdf5a61d9..8d76990a2 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h @@ -540,7 +540,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums #define TCPIP_THREAD_NAME "tcp" #define TCPIP_THREAD_STACKSIZE 2048 #define TCPIP_MBOX_SIZE 16 -#define TCPIP_THREAD_PRIO 20 +#define TCPIP_THREAD_PRIO 30 /* ---------------------------------------- diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c index e491c5cb1..e6f405af0 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/sys_arch.c @@ -31,55 +31,54 @@ */ /** -* @file sys_arch.c -* @brief In order to adapt to XiZi, some changes have been made to implement the LwIP interface. -* @version 1.0 -* @author AIIT XUOS Lab -* @date 2021-05-29 -*/ + * @file sys_arch.c + * @brief In order to adapt to XiZi, some changes have been made to implement the LwIP interface. + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2021-05-29 + */ #include "debug.h" -#include #include +#include -#include "tcpip.h" +#include "lwip/dhcp.h" #include "lwip/init.h" #include "lwip/netif.h" #include "lwip/sio.h" -#include -#include -#include -#include "lwip/dhcp.h" +#include "tcpip.h" #include "tcpip_priv.h" +#include +#include +#include #if !NO_SYS #include "sys_arch.h" #endif #include +#include #include #include -#include -#include -#include -#include #include +#include +#include #include "board.h" -#include "ethernet.h" #include "connect_ethernet.h" +#include "ethernet.h" -char lwip_ipaddr[20] = {192, 168, 130, 77}; -char lwip_netmask[20] = {255, 255, 254, 0}; -char lwip_gwaddr[20] = {192, 168, 130, 1}; +char lwip_ipaddr[20] = { 192, 168, 130, 77 }; +char lwip_netmask[20] = { 255, 255, 254, 0 }; +char lwip_gwaddr[20] = { 192, 168, 130, 1 }; -char lwip_eth0_ipaddr[20] = {192, 168, 130, 77}; -char lwip_eth0_netmask[20] = {255, 255, 254, 0}; -char lwip_eth0_gwaddr[20] = {192, 168, 130, 1}; +char lwip_eth0_ipaddr[20] = { 192, 168, 130, 77 }; +char lwip_eth0_netmask[20] = { 255, 255, 254, 0 }; +char lwip_eth0_gwaddr[20] = { 192, 168, 130, 1 }; -char lwip_eth1_ipaddr[20] = {192, 168, 130, 99}; -char lwip_eth1_netmask[20] = {255, 255, 254, 0}; -char lwip_eth1_gwaddr[20] = {192, 168, 130, 23}; +char lwip_eth1_ipaddr[20] = { 192, 168, 130, 99 }; +char lwip_eth1_netmask[20] = { 255, 255, 254, 0 }; +char lwip_eth1_gwaddr[20] = { 192, 168, 130, 23 }; char lwip_flag = 0; @@ -88,220 +87,238 @@ x_ticks_t lwip_sys_now; #define SYS_THREAD_MAX 4 struct netif gnetif; -sys_sem_t* get_eth_recv_sem() { +sys_sem_t* get_eth_recv_sem() +{ static sys_sem_t g_recv_sem = 0; return &g_recv_sem; } -void sys_init(void) { - // do nothing +void sys_init(void) +{ + // do nothing } -u32_t -sys_jiffies(void) { - lwip_sys_now = CurrentTicksGain(); - return lwip_sys_now; +u32_t sys_jiffies(void) +{ + lwip_sys_now = CurrentTicksGain(); + return lwip_sys_now; } -u32_t -sys_now(void) { - lwip_sys_now = CurrentTicksGain(); - return CalculateTimeMsFromTick(lwip_sys_now); +u32_t sys_now(void) +{ + lwip_sys_now = CurrentTicksGain(); + return CalculateTimeMsFromTick(lwip_sys_now); } -sys_prot_t sys_arch_protect(void) { - return CriticalAreaLock(); +sys_prot_t sys_arch_protect(void) +{ + return CriticalAreaLock(); } -void sys_arch_unprotect(sys_prot_t pval) { - CriticalAreaUnLock(pval); +void sys_arch_unprotect(sys_prot_t pval) +{ + CriticalAreaUnLock(pval); } #if !NO_SYS -err_t -sys_sem_new(sys_sem_t *sem, u8_t count) { - *sem = KSemaphoreCreate((uint16)count); +err_t sys_sem_new(sys_sem_t* sem, u8_t count) +{ + *sem = KSemaphoreCreate((uint16)count); #if SYS_STATS - ++lwip_stats.sys.sem.used; - if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { - lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; - } -#endif /* SYS_STATS */ - - if(*sem >= 0) - return ERR_OK; - else { -#if SYS_STATS - ++lwip_stats.sys.sem.err; -#endif /* SYS_STATS */ - KPrintf("[sys_arch]:new sem fail!\n"); - return ERR_MEM; - } -} - -void -sys_sem_free(sys_sem_t *sem) { -#if SYS_STATS - --lwip_stats.sys.sem.used; -#endif /* SYS_STATS */ - KSemaphoreDelete(*sem); - *sem = SYS_SEM_NULL; -} - -int sys_sem_valid(sys_sem_t *sem) { - return (*sem > SYS_SEM_NULL); -} - -void -sys_sem_set_invalid(sys_sem_t *sem) { - *sem = SYS_SEM_NULL; -} - -u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) { - x_ticks_t start_tick = 0 ; - int32 wait_time = 0; - - - if(*sem == SYS_SEM_NULL) - return SYS_ARCH_TIMEOUT; - - - start_tick = CurrentTicksGain(); - - if (0 == timeout) - wait_time = WAITING_FOREVER; - else - wait_time = timeout; - - - if(KSemaphoreObtain(*sem, wait_time) == EOK) - return CalculateTimeMsFromTick(CurrentTicksGain()-start_tick); - else - return SYS_ARCH_TIMEOUT; -} - -void sys_sem_signal(sys_sem_t *sem) { - if(KSemaphoreAbandon(*sem) != EOK) - KPrintf("[sys_arch]:sem signal fail!\n"); -} - -err_t sys_mutex_new(sys_mutex_t *mutex) { - *mutex = KMutexCreate(); - if (*mutex > SYS_MRTEX_NULL) - return ERR_OK; - else { - KPrintf("[sys_arch]:new mutex fail!\n"); - return ERR_MEM; - } -} - -void sys_mutex_free(sys_mutex_t *mutex) { - KMutexDelete(*mutex); -} - -void sys_mutex_set_invalid(sys_mutex_t *mutex) { - *mutex = SYS_MRTEX_NULL; -} - -void sys_mutex_lock(sys_mutex_t *mutex) { - KMutexObtain(*mutex, WAITING_FOREVER); -} - -void sys_mutex_unlock(sys_mutex_t *mutex) { - KMutexAbandon(*mutex); -} - - -sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) { - sys_thread_t handle = -1; - handle = KTaskCreate(name, - function, - arg, - (uint32)stacksize, - (uint8)prio); - if (handle >= 0) { - StartupKTask(handle); - lw_print("lw: [%s] create %s handle %x\n", __func__, name, handle); - return handle; - } - lw_print("lw: [%s] create %s failed\n", __func__, name); - return -ERROR; -} - -err_t sys_mbox_new(sys_mbox_t *mbox, int size) { - *mbox = KCreateMsgQueue(sizeof(void *), size); - -#if SYS_STATS - ++lwip_stats.sys.mbox.used; - if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { - lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + ++lwip_stats.sys.sem.used; + if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { + lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; } #endif /* SYS_STATS */ - if(*mbox < 0) { - lw_print("lw: [%s] alloc %d mbox %p failed\n", __func__, size, mbox); - return ERR_MEM; - } - lw_print("lw: [%s] alloc %d mbox %p ok!\n", __func__, size, mbox); - return ERR_OK; + if (*sem >= 0) + return ERR_OK; + else { +#if SYS_STATS + ++lwip_stats.sys.sem.err; +#endif /* SYS_STATS */ + KPrintf("[sys_arch]:new sem fail!\n"); + return ERR_MEM; + } } -void sys_mbox_free(sys_mbox_t *mbox) { - KDeleteMsgQueue(*mbox); +void sys_sem_free(sys_sem_t* sem) +{ +#if SYS_STATS + --lwip_stats.sys.sem.used; +#endif /* SYS_STATS */ + KSemaphoreDelete(*sem); + *sem = SYS_SEM_NULL; } -int sys_mbox_valid(sys_mbox_t *mbox) { - if (*mbox <= SYS_MBOX_NULL) - return 0; - else - return 1; +int sys_sem_valid(sys_sem_t* sem) +{ + return (*sem > SYS_SEM_NULL); } -void sys_mbox_set_invalid(sys_mbox_t *mbox) { - *mbox = SYS_MBOX_NULL; +void sys_sem_set_invalid(sys_sem_t* sem) +{ + *sem = SYS_SEM_NULL; } -void sys_mbox_post(sys_mbox_t *q, void *msg) { - KMsgQueueSendwait(*q, &msg, sizeof(void *), WAITING_FOREVER); +u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) +{ + x_ticks_t start_tick = 0; + int32 wait_time = 0; + + if (*sem == SYS_SEM_NULL) + return SYS_ARCH_TIMEOUT; + + start_tick = CurrentTicksGain(); + + if (0 == timeout) + wait_time = WAITING_FOREVER; + else + wait_time = timeout; + + if (KSemaphoreObtain(*sem, wait_time) == EOK) + return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick); + else + return SYS_ARCH_TIMEOUT; } -err_t sys_mbox_trypost(sys_mbox_t *q, void *msg) { - // if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK) - if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK) +void sys_sem_signal(sys_sem_t* sem) +{ + if (KSemaphoreAbandon(*sem) != EOK) + KPrintf("[sys_arch]:sem signal fail!\n"); +} + +err_t sys_mutex_new(sys_mutex_t* mutex) +{ + *mutex = KMutexCreate(); + if (*mutex > SYS_MRTEX_NULL) + return ERR_OK; + else { + KPrintf("[sys_arch]:new mutex fail!\n"); + return ERR_MEM; + } +} + +void sys_mutex_free(sys_mutex_t* mutex) +{ + KMutexDelete(*mutex); +} + +void sys_mutex_set_invalid(sys_mutex_t* mutex) +{ + *mutex = SYS_MRTEX_NULL; +} + +void sys_mutex_lock(sys_mutex_t* mutex) +{ + KMutexObtain(*mutex, WAITING_FOREVER); +} + +void sys_mutex_unlock(sys_mutex_t* mutex) +{ + KMutexAbandon(*mutex); +} + +sys_thread_t sys_thread_new(const char* name, lwip_thread_fn function, void* arg, int stacksize, int prio) +{ + sys_thread_t handle = -1; + handle = KTaskCreate(name, + function, + arg, + (uint32)stacksize, + (uint8)prio); + if (handle >= 0) { + StartupKTask(handle); + lw_print("lw: [%s] create %s handle %x\n", __func__, name, handle); + return handle; + } + lw_print("lw: [%s] create %s failed\n", __func__, name); + return -ERROR; +} + +err_t sys_mbox_new(sys_mbox_t* mbox, int size) +{ + *mbox = KCreateMsgQueue(sizeof(void*), size); + +#if SYS_STATS + ++lwip_stats.sys.mbox.used; + if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) { + lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used; + } +#endif /* SYS_STATS */ + if (*mbox < 0) { + lw_print("lw: [%s] alloc %d mbox %p failed\n", __func__, size, mbox); + return ERR_MEM; + } + + lw_print("lw: [%s] alloc %d mbox %p ok!\n", __func__, size, mbox); return ERR_OK; - else - return ERR_MEM; } -err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg) { - return sys_mbox_trypost(q, msg); +void sys_mbox_free(sys_mbox_t* mbox) +{ + KDeleteMsgQueue(*mbox); } -u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout) { - x_ticks_t start_tick = 0 ; - int32 wait_time = 0; - - start_tick = CurrentTicksGain(); - - if (0 == timeout) - wait_time = WAITING_FOREVER; - else - wait_time = timeout; - - if(KMsgQueueRecv(*q, &(*msg), sizeof(void *), wait_time) == EOK) { - return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick); - } else { - return SYS_ARCH_TIMEOUT; - } +int sys_mbox_valid(sys_mbox_t* mbox) +{ + if (*mbox <= SYS_MBOX_NULL) + return 0; + else + return 1; } -u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg) { - if (KMsgQueueRecv(*q, &(*msg), sizeof(void *), 0) == EOK) - return ERR_OK; - else - return SYS_MBOX_EMPTY; +void sys_mbox_set_invalid(sys_mbox_t* mbox) +{ + *mbox = SYS_MBOX_NULL; +} + +void sys_mbox_post(sys_mbox_t* q, void* msg) +{ + KMsgQueueSendwait(*q, &msg, sizeof(void*), WAITING_FOREVER); +} + +err_t sys_mbox_trypost(sys_mbox_t* q, void* msg) +{ + // if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK) + if (KMsgQueueSend(*q, &msg, sizeof(void*)) == EOK) + return ERR_OK; + else + return ERR_MEM; +} + +err_t sys_mbox_trypost_fromisr(sys_mbox_t* q, void* msg) +{ + return sys_mbox_trypost(q, msg); +} + +u32_t sys_arch_mbox_fetch(sys_mbox_t* q, void** msg, u32_t timeout) +{ + x_ticks_t start_tick = 0; + int32 wait_time = 0; + + start_tick = CurrentTicksGain(); + + if (0 == timeout) + wait_time = WAITING_FOREVER; + else + wait_time = timeout; + + if (KMsgQueueRecv(*q, &(*msg), sizeof(void*), wait_time) == EOK) { + return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick); + } else { + return SYS_ARCH_TIMEOUT; + } +} + +u32_t sys_arch_mbox_tryfetch(sys_mbox_t* q, void** msg) +{ + if (KMsgQueueRecv(*q, &(*msg), sizeof(void*), 0) == EOK) + return ERR_OK; + else + return SYS_MBOX_EMPTY; } #if LWIP_NETCONN_SEM_PER_THREAD @@ -315,128 +332,136 @@ ip4_addr_t ipaddr; ip4_addr_t netmask; ip4_addr_t gw; -void lwip_config_input(struct netif *net) { - sys_thread_t th_id = 0; +void lwip_config_input(struct netif* net) +{ + sys_thread_t th_id = 0; - th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 20); + 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) { - ip4_addr_t net_ipaddr, net_netmask, net_gw; - char* eth_cfg; +void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw) +{ + static char is_init = 0; + if (is_init != 0) { + return; + } + is_init = 1; - eth_cfg = ethernetif_config_enet_set(enet_port); + sys_sem_new(get_eth_recv_sem(), 0); - if(chk_lwip_bit(LWIP_INIT_FLAG)) { - lw_print("lw: [%s] already ...\n", __func__); - return; - } + ip4_addr_t net_ipaddr, net_netmask, net_gw; + char* eth_cfg; - set_lwip_bit(LWIP_INIT_FLAG); + eth_cfg = ethernetif_config_enet_set(enet_port); - tcpip_init(NULL, NULL); + if (chk_lwip_bit(LWIP_INIT_FLAG)) { + lw_print("lw: [%s] already ...\n", __func__); + return; + } - lw_print("lw: [%s] start ...\n", __func__); + set_lwip_bit(LWIP_INIT_FLAG); - IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); - IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); - IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); + tcpip_init(NULL, NULL); - if (0 == enet_port) { -#ifdef NETIF_ENET0_INIT_FUNC - printf("[%s:%d] call netif_add\n", __func__, __LINE__); - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, - tcpip_input); -#endif - } else if (1 == enet_port) { -#ifdef NETIF_ENET1_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, - tcpip_input); -#endif - } - - netif_set_default(&gnetif); - netif_set_up(&gnetif); - - lw_print("\r\n************************************************\r\n"); - lw_print(" Network Configuration\r\n"); - lw_print("************************************************\r\n"); - lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1], - ((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]); - lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1], - ((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]); - lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1], - ((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]); - lw_print("************************************************\r\n"); - - lwip_config_input(&gnetif); -} - - -void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw) { - ip4_addr_t net_ipaddr, net_netmask, net_gw; - char* eth_cfg; - - eth_cfg = ethernetif_config_enet_set(enet_port); - - if(chk_lwip_bit(LWIP_INIT_FLAG)) { - lw_print("lw: [%s] already ...\n", __func__); + lw_print("lw: [%s] start ...\n", __func__); IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); - // update ip addr - netif_set_down(&gnetif); - netif_set_gw(&gnetif, &net_gw); - netif_set_netmask(&gnetif, &net_netmask); - netif_set_ipaddr(&gnetif, &net_ipaddr); - netif_set_up(&gnetif); - return; - } - set_lwip_bit(LWIP_INIT_FLAG); - - lw_print("lw: [%s] start ...\n", __func__); - - IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); - IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); - IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); - - lwip_init(); - - if(0 == enet_port) { + if (0 == enet_port) { #ifdef NETIF_ENET0_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, - ethernet_input); + netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, + tcpip_input); #endif - } else if (1 == enet_port) { + } else if (1 == enet_port) { #ifdef NETIF_ENET1_INIT_FUNC - netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, - ethernet_input); + netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, + tcpip_input); #endif - } - - netif_set_default(&gnetif); - netif_set_up(&gnetif); + } - if(chk_lwip_bit(LWIP_PRINT_FLAG)) { - lw_notice("\r\n************************************************\r\n"); - lw_notice(" Network Configuration\r\n"); - lw_notice("************************************************\r\n"); - lw_notice(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1], - ((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]); - lw_notice(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1], - ((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]); - lw_notice(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1], - ((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]); - lw_notice("************************************************\r\n"); - } - lwip_config_input(&gnetif); + netif_set_default(&gnetif); + netif_set_up(&gnetif); + + lw_print("\r\n************************************************\r\n"); + lw_print(" Network Configuration\r\n"); + lw_print("************************************************\r\n"); + lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], + ((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]); + lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], + ((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]); + lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], + ((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]); + lw_print("************************************************\r\n"); + + lwip_config_input(&gnetif); } +void lwip_config_net(uint8_t enet_port, char* ip, char* mask, char* gw) +{ + ip4_addr_t net_ipaddr, net_netmask, net_gw; + char* eth_cfg; + + eth_cfg = ethernetif_config_enet_set(enet_port); + + if (chk_lwip_bit(LWIP_INIT_FLAG)) { + lw_print("lw: [%s] already ...\n", __func__); + + IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); + IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); + IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); + + // update ip addr + netif_set_down(&gnetif); + netif_set_gw(&gnetif, &net_gw); + netif_set_netmask(&gnetif, &net_netmask); + netif_set_ipaddr(&gnetif, &net_ipaddr); + netif_set_up(&gnetif); + return; + } + set_lwip_bit(LWIP_INIT_FLAG); + + lw_print("lw: [%s] start ...\n", __func__); + + IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]); + IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]); + IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]); + + lwip_init(); + + if (0 == enet_port) { +#ifdef NETIF_ENET0_INIT_FUNC + netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC, + ethernet_input); +#endif + } else if (1 == enet_port) { +#ifdef NETIF_ENET1_INIT_FUNC + netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC, + ethernet_input); +#endif + } + + netif_set_default(&gnetif); + netif_set_up(&gnetif); + + if (chk_lwip_bit(LWIP_PRINT_FLAG)) { + lw_notice("\r\n************************************************\r\n"); + lw_notice(" Network Configuration\r\n"); + lw_notice("************************************************\r\n"); + lw_notice(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1], + ((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]); + lw_notice(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1], + ((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]); + lw_notice(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1], + ((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]); + lw_notice("************************************************\r\n"); + } + lwip_config_input(&gnetif); +} diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4_addr.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4_addr.c index 33204d114..432b06361 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4_addr.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/core/ipv4/ip4_addr.c @@ -314,7 +314,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) *rp++ = '.'; ap++; } - *--rp = 0; + *--rp = '\0'; return buf; } diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/Makefile b/Ubiquitous/XiZi_IIoT/resources/ethernet/Makefile index 7de558d34..97452c54f 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/Makefile @@ -1,4 +1,4 @@ -SRC_DIR += cmd_lwip +SRC_DIR += cmd_lwip netdev LWIP_DIR := LwIP include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile index 697c6c141..cd4019ebb 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile @@ -1,4 +1,4 @@ -SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c +SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c # SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c index 29c947a18..e2389af3c 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c @@ -50,7 +50,7 @@ static void iperf_udp_client(void *thread_param) send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ; sock = socket(PF_INET, SOCK_DGRAM, 0); - if(sock < 0){ + if(sock < 0) { KPrintf("[%s:%d] can't create socket! exit!\n", __FILE__, __LINE__); return; } @@ -60,21 +60,21 @@ static void iperf_udp_client(void *thread_param) server.sin_addr.s_addr = inet_addr(param.host); memset(&(server.sin_zero), 0, sizeof(server.sin_zero)); - if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))){ + if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))) { lw_error("Unable to connect\n"); closesocket(sock); return; } buffer = malloc(IPERF_BUFSZ); - if (buffer == NULL){ + if (buffer == NULL) { printf("[%s:%d] malloc failed\n", __FILE__, __LINE__); return; } memset(buffer, 0x00, IPERF_BUFSZ); KPrintf("iperf udp mode run...\n"); - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { packet_count++; tick = CurrentTicksGain(); buffer[0] = htonl(packet_count); @@ -101,12 +101,12 @@ static void iperf_udp_server(void *thread_param) struct timeval timeout; buffer = malloc(IPERF_BUFSZ); - if (buffer == NULL){ + if (buffer == NULL) { return; } sock = socket(PF_INET, SOCK_DGRAM, 0); - if(sock < 0){ + if(sock < 0) { KPrintf("can't create socket! exit!"); return; } @@ -117,35 +117,34 @@ static void iperf_udp_server(void *thread_param) timeout.tv_sec = 2; timeout.tv_usec = 0; - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1){ + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { KPrintf("setsockopt failed!"); closesocket(sock); free(buffer); return; } - if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0){ + if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) { KPrintf("iperf server bind failed! exit!"); closesocket(sock); free(buffer); return; } - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { tick1 = CurrentTicksGain(); tick2 = tick1; lost = 0; total = 0; sentlen = 0; - while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){ + while ((tick2 - tick1) < (TICK_PER_SECOND * 5)) { r_size = recvfrom(sock, buffer, IPERF_BUFSZ, 0, (struct sockaddr *)&sender, (socklen_t*)&sender_len); - if (r_size > 12){ + if (r_size > 12) { pcount = ntohl(buffer[0]); - if (last_pcount < pcount){ + if (last_pcount < pcount) { lost += pcount - last_pcount - 1; total += pcount - last_pcount; - } - else{ + } else { last_pcount = pcount; } last_pcount = pcount; @@ -153,7 +152,7 @@ static void iperf_udp_server(void *thread_param) } tick2 = CurrentTicksGain(); } - if (sentlen > 0){ + if (sentlen > 0) { long data; int integer, decimal; KTaskDescriptorType tid; @@ -186,10 +185,9 @@ static void iperf_client(void *thread_param) for (i = 0; i < IPERF_BUFSZ; i ++) send_buf[i] = i & 0xff; - while (param.mode != IPERF_MODE_STOP) - { + while (param.mode != IPERF_MODE_STOP) { sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0){ + if (sock < 0) { KPrintf("create socket failed!"); DelayKTask(TICK_PER_SECOND); continue; @@ -200,8 +198,8 @@ static void iperf_client(void *thread_param) addr.sin_addr.s_addr = inet_addr((char *)param.host); ret = connect(sock, (const struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1){ - if (tips){ + if (ret == -1) { + if (tips) { KPrintf("Connect to iperf server faile, Waiting for the server to open!"); tips = 0; } @@ -224,9 +222,9 @@ static void iperf_client(void *thread_param) sentlen = 0; tick1 = CurrentTicksGain(); - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { tick2 = CurrentTicksGain(); - if (tick2 - tick1 >= TICK_PER_SECOND * 5){ + if (tick2 - tick1 >= TICK_PER_SECOND * 5) { double speed; // int integer, decimal; KTaskDescriptorType tid; @@ -240,7 +238,7 @@ static void iperf_client(void *thread_param) } ret = send(sock, send_buf, IPERF_BUFSZ, 0); - if (ret > 0){ + if (ret > 0) { sentlen += ret; } @@ -264,7 +262,7 @@ struct sock_conn_cb { int parent_id; }; -void iperf_sever_worker(void* arg) { +void iperf_server_worker(void* arg) { struct sock_conn_cb *sccb = (struct sock_conn_cb *)arg; x_ticks_t tick1, tick2; @@ -287,7 +285,7 @@ void iperf_sever_worker(void* arg) { int cur_tid = GetKTaskDescriptor()->id.id; tick1 = CurrentTicksGain(); - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { bytes_received = recv(sccb->connected, recv_data, IPERF_BUFSZ, 0); if (bytes_received == 0) { KPrintf("client disconnected (%s, %d)\n", @@ -336,7 +334,7 @@ void iperf_server_multithread(void *thread_param) struct timeval timeout; sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0){ + if (sock < 0) { KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__); goto __exit; } @@ -346,12 +344,12 @@ void iperf_server_multithread(void *thread_param) server_addr.sin_addr.s_addr = INADDR_ANY; memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); - if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { KPrintf("Unable to bind!\n"); goto __exit; } - if (listen(sock, 5) == -1){ + if (listen(sock, 5) == -1) { KPrintf("Listen error!\n"); goto __exit; } @@ -360,7 +358,7 @@ void iperf_server_multithread(void *thread_param) timeout.tv_sec = 5; timeout.tv_usec = 0; - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { FD_ZERO(&readset); FD_SET(sock, &readset); @@ -379,8 +377,8 @@ void iperf_server_multithread(void *thread_param) sccb->client_addr = client_addr; sccb->server_addr = server_addr; sccb->parent_id = cur_tid; - int tid = KTaskCreate("iperf server", iperf_sever_worker, sccb, LWIP_TASK_STACK_SIZE, 20); - // iperf_sever_worker(sccb); + int tid = KTaskCreate("iperf server", iperf_server_worker, sccb, LWIP_TASK_STACK_SIZE, 20); + // iperf_server_worker(sccb); if (tid) { StartupKTask(tid); } else { @@ -405,13 +403,13 @@ void iperf_server(void *thread_param) struct timeval timeout; sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0){ + if (sock < 0) { KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__); goto __exit; } recv_data = (uint8_t *)malloc(IPERF_BUFSZ); - if (recv_data == NULL){ + if (recv_data == NULL) { KPrintf("No memory!\n"); goto __exit; } @@ -421,12 +419,12 @@ void iperf_server(void *thread_param) server_addr.sin_addr.s_addr = INADDR_ANY; memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); - if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { KPrintf("Unable to bind!\n"); goto __exit; } - if (listen(sock, 5) == -1){ + if (listen(sock, 5) == -1) { KPrintf("Listen error!\n"); goto __exit; } @@ -434,7 +432,7 @@ void iperf_server(void *thread_param) timeout.tv_sec = 3; timeout.tv_usec = 0; - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { FD_ZERO(&readset); FD_SET(sock, &readset); @@ -458,7 +456,7 @@ void iperf_server(void *thread_param) recvlen = 0; tick1 = CurrentTicksGain(); - while (param.mode != IPERF_MODE_STOP){ + while (param.mode != IPERF_MODE_STOP) { bytes_received = recv(connected, recv_data, IPERF_BUFSZ, 0); if (bytes_received == 0) { KPrintf("client disconnected (%s, %d)\n", @@ -526,48 +524,37 @@ int iperf(int argc, char **argv) int use_udp = 0; int index = 1; - if (argc == 1) - { + if (argc == 1) { goto __usage; } - if (strcmp(argv[1], "-u") == 0) - { + if (strcmp(argv[1], "-u") == 0) { index = 2; use_udp = 1; } if (strcmp(argv[index], "-h") == 0) goto __usage; - else if (strcmp(argv[index], "--stop") == 0) - { + else if (strcmp(argv[index], "--stop") == 0) { /* stop iperf */ param.mode = IPERF_MODE_STOP; printf("iperf stop.\n"); return 0; - } - else if (strcmp(argv[index], "-s") == 0) - { + } else if (strcmp(argv[index], "-s") == 0) { mode = IPERF_MODE_SERVER; /* server mode */ /* iperf -s -p 5000 */ - if (argc >= 4) - { - if (strcmp(argv[index + 1], "-p") == 0) - { + if (argc >= 4) { + if (strcmp(argv[index + 1], "-p") == 0) { port = atoi(argv[index + 2]); } else goto __usage; } - } - else if (strcmp(argv[index], "-c") == 0) - { + } else if (strcmp(argv[index], "-c") == 0) { mode = IPERF_MODE_CLIENT; /* client mode */ if (argc < 3) goto __usage; host = argv[index + 1]; - if (argc >= 5) - { + if (argc >= 5) { /* iperf -c host -p port */ - if (strcmp(argv[index + 2], "-p") == 0) - { + if (strcmp(argv[index + 2], "-p") == 0) { port = atoi(argv[index + 3]); } else goto __usage; @@ -575,57 +562,43 @@ int iperf(int argc, char **argv) } else goto __usage; - if (argc >= 7) - { - if(strcmp(argv[argc - 2], "-m") == 0) - { + if (argc >= 7) { + if(strcmp(argv[argc - 2], "-m") == 0) { numtid = atoi(argv[argc - 1]); } else goto __usage; } /* start iperf */ - if (param.mode == IPERF_MODE_STOP) - { + if (param.mode == IPERF_MODE_STOP) { int i = 0; char tid_name[NAME_NUM_MAX + 1] = {0}; param.mode = mode; param.port = port; - if (param.host) - { + if (param.host) { free(param.host); param.host = NULL; } if (host) param.host = strdup(host); - for (i = 0; i < numtid; i++) - { + for (i = 0; i < numtid; i++) { int32 tid = 0; void (*function)(void *parameter); - if (use_udp) - { - if (mode == IPERF_MODE_CLIENT) - { + if (use_udp) { + if (mode == IPERF_MODE_CLIENT) { snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1); function = iperf_udp_client; - } - else if (mode == IPERF_MODE_SERVER) - { + } else if (mode == IPERF_MODE_SERVER) { snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1); function = iperf_udp_server; } - } - else - { - if (mode == IPERF_MODE_CLIENT) - { + } else { + if (mode == IPERF_MODE_CLIENT) { snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1); function = iperf_client; - } - else if (mode == IPERF_MODE_SERVER) - { + } else if (mode == IPERF_MODE_SERVER) { snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1); function = iperf_server_multithread; } @@ -634,9 +607,7 @@ int iperf(int argc, char **argv) tid = KTaskCreate(tid_name, function, NULL, LWIP_TASK_STACK_SIZE, 20); if (tid) StartupKTask(tid); } - } - else - { + } else { KPrintf("Please stop iperf firstly, by:\n"); KPrintf("iperf --stop\n"); } diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c index 8355989e2..8856be9ff 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_config_demo.c @@ -19,48 +19,45 @@ */ #include -#include #include -#include #include +#include +#include +#include + +#include /******************************************************************************/ uint8_t enet_id = 0; -static void LwipSetIPTask(void *param) +static void LwipSetIPTask(void* param) { - uint8_t enet_port = *(uint8_t *)param; ///< test enet port + uint8_t enet_port = *(uint8_t*)param; ///< test enet port printf("lw: [%s] config netport id[%d]\n", __func__, enet_port); // lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); } -void LwipSetIPTest(int argc, char *argv[]) +void LwipSetIPTest(int argc, char* argv[]) { - if(argc >= 4) - { + if (argc >= 4) { printf("lw: [%s] ip %s mask %s gw %s netport %s\n", __func__, argv[1], argv[2], argv[3], argv[4]); sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]); sscanf(argv[2], "%d.%d.%d.%d", &lwip_netmask[0], &lwip_netmask[1], &lwip_netmask[2], &lwip_netmask[3]); sscanf(argv[3], "%d.%d.%d.%d", &lwip_gwaddr[0], &lwip_gwaddr[1], &lwip_gwaddr[2], &lwip_gwaddr[3]); sscanf(argv[4], "%d", &enet_id); - if(0 == enet_id) - { + if (0 == enet_id) { printf("save eth0 info\n"); memcpy(lwip_eth0_ipaddr, lwip_ipaddr, 20); memcpy(lwip_eth0_netmask, lwip_netmask, 20); memcpy(lwip_eth0_gwaddr, lwip_gwaddr, 20); - } - else if(1 == enet_id) - { + } else if (1 == enet_id) { printf("save eth1 info\n"); memcpy(lwip_eth1_ipaddr, lwip_ipaddr, 20); memcpy(lwip_eth1_netmask, lwip_netmask, 20); memcpy(lwip_eth1_gwaddr, lwip_gwaddr, 20); } - } - else if(argc == 2) - { + } else if (argc == 2) { printf("lw: [%s] set eth0 ipaddr %s \n", __func__, argv[1]); sscanf(argv[1], "%d.%d.%d.%d", &lwip_ipaddr[0], &lwip_ipaddr[1], &lwip_ipaddr[2], &lwip_ipaddr[3]); memcpy(lwip_eth0_ipaddr, lwip_ipaddr, strlen(lwip_ipaddr)); @@ -70,39 +67,56 @@ void LwipSetIPTest(int argc, char *argv[]) } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5), - setip, LwipSetIPTest, setip [IP] [Netmask] [Gateway] [port]); + setip, LwipSetIPTest, setip[IP][Netmask][Gateway][port]); - -void LwipShowIPTask(int argc, char *argv[]) +void LwipShowIPTask(int argc, char* argv[]) { #ifdef configMAC_ADDR char mac_addr0[] = configMAC_ADDR; #endif + // find default netdev + struct netdev* netdev = netdev_get_by_name("en\0"); + if (netdev == NULL) { + lw_notice("[%s] Netdev not found by name en\n"); + struct netdev* default_netdev = NETDEV_DEFAULT; + } + lw_notice("\r\n************************************************\r\n"); lw_notice(" Network Configuration\r\n"); lw_notice("************************************************\r\n"); - lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_eth0_ipaddr)[0], ((u8_t *)&lwip_eth0_ipaddr)[1], - ((u8_t *)&lwip_eth0_ipaddr)[2], ((u8_t *)&lwip_eth0_ipaddr)[3]); - lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_eth0_netmask)[0], ((u8_t *)&lwip_eth0_netmask)[1], - ((u8_t *)&lwip_eth0_netmask)[2], ((u8_t *)&lwip_eth0_netmask)[3]); - lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_gwaddr)[0], ((u8_t *)&lwip_eth0_gwaddr)[1], - ((u8_t *)&lwip_eth0_gwaddr)[2], ((u8_t *)&lwip_eth0_gwaddr)[3]); + // lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_ipaddr)[0], ((u8_t*)&lwip_eth0_ipaddr)[1], + // ((u8_t*)&lwip_eth0_ipaddr)[2], ((u8_t*)&lwip_eth0_ipaddr)[3]); + // lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_netmask)[0], ((u8_t*)&lwip_eth0_netmask)[1], + // ((u8_t*)&lwip_eth0_netmask)[2], ((u8_t*)&lwip_eth0_netmask)[3]); + // lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_gwaddr)[0], ((u8_t*)&lwip_eth0_gwaddr)[1], + // ((u8_t*)&lwip_eth0_gwaddr)[2], ((u8_t*)&lwip_eth0_gwaddr)[3]); + // #ifdef configMAC_ADDR + // lw_notice(" ETH0 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr0[0], mac_addr0[1], mac_addr0[2], + // mac_addr0[3], mac_addr0[4], mac_addr0[5]); + // #endif + + lw_notice(" ETH0 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_ipaddr)[0], ((u8_t*)&lwip_eth0_ipaddr)[1], + ((u8_t*)&lwip_eth0_ipaddr)[2], ((u8_t*)&lwip_eth0_ipaddr)[3]); + lw_notice(" ETH0 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth0_netmask)[0], ((u8_t*)&lwip_eth0_netmask)[1], + ((u8_t*)&lwip_eth0_netmask)[2], ((u8_t*)&lwip_eth0_netmask)[3]); + lw_notice(" ETH0 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_gwaddr)[0], ((u8_t*)&lwip_eth0_gwaddr)[1], + ((u8_t*)&lwip_eth0_gwaddr)[2], ((u8_t*)&lwip_eth0_gwaddr)[3]); #ifdef configMAC_ADDR lw_notice(" ETH0 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr0[0], mac_addr0[1], mac_addr0[2], mac_addr0[3], mac_addr0[4], mac_addr0[5]); #endif + #ifdef BOARD_NET_COUNT - if(BOARD_NET_COUNT > 1) - { + if (BOARD_NET_COUNT > 1) { char mac_addr1[] = configMAC_ADDR_ETH1; lw_notice("\r\n"); - lw_notice(" ETH1 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_eth1_ipaddr)[0], ((u8_t *)&lwip_eth1_ipaddr)[1], - ((u8_t *)&lwip_eth1_ipaddr)[2], ((u8_t *)&lwip_eth1_ipaddr)[3]); - lw_notice(" ETH1 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_eth1_netmask)[0], ((u8_t *)&lwip_eth1_netmask)[1], - ((u8_t *)&lwip_eth1_netmask)[2], ((u8_t *)&lwip_eth1_netmask)[3]); - lw_notice(" ETH1 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&lwip_eth1_gwaddr)[0], ((u8_t *)&lwip_eth1_gwaddr)[1], - ((u8_t *)&lwip_eth1_gwaddr)[2], ((u8_t *)&lwip_eth1_gwaddr)[3]); + lw_notice(" ETH1 IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_ipaddr)[0], ((u8_t*)&lwip_eth1_ipaddr)[1], + ((u8_t*)&lwip_eth1_ipaddr)[2], ((u8_t*)&lwip_eth1_ipaddr)[3]); + lw_notice(" ETH1 IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_netmask)[0], ((u8_t*)&lwip_eth1_netmask)[1], + ((u8_t*)&lwip_eth1_netmask)[2], ((u8_t*)&lwip_eth1_netmask)[3]); + lw_notice(" ETH1 IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&lwip_eth1_gwaddr)[0], ((u8_t*)&lwip_eth1_gwaddr)[1], + ((u8_t*)&lwip_eth1_gwaddr)[2], ((u8_t*)&lwip_eth1_gwaddr)[3]); lw_notice(" ETH1 MAC Address : %x:%x:%x:%x:%x:%x\r\n", mac_addr1[0], mac_addr1[1], mac_addr1[2], mac_addr1[3], mac_addr1[4], mac_addr1[5]); } @@ -111,5 +125,4 @@ void LwipShowIPTask(int argc, char *argv[]) } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), - showip, LwipShowIPTask, GetIp [IP] [Netmask] [Gateway]); - + showip, LwipShowIPTask, GetIp[IP][Netmask][Gateway]); diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_tcp_demo.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_tcp_demo.c index e1ad56550..1a5fd37bc 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_tcp_demo.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_tcp_demo.c @@ -27,8 +27,8 @@ #include "lwip/sockets.h" #include "tcpecho_raw.h" char tcp_demo_msg[LWIP_TEST_MSG_SIZE] = { 0 }; -char tcp_demo_ip[] = {192, 168, 250, 252}; -u16_t tcp_demo_port = 80; +char tcp_server_ip[] = {192, 168, 130, 2}; +u16_t tcp_server_port = 80; int tcp_send_num = 0; int tcp_send_task_on = 0; uint32 tcp_interval = 50; @@ -39,14 +39,14 @@ static void LwipTcpSendTask(void *arg) { int fd = -1; fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd < 0) - { - lw_error("Socket error\n"); + if (fd < 0) { + KPrintf("Socket error\n"); return; } LwipTcpSocketParamType *param = (LwipTcpSocketParamType *)arg; + //configure tcp client param struct sockaddr_in tcp_sock; tcp_sock.sin_family = AF_INET; tcp_sock.sin_port = htons(param->port); @@ -55,24 +55,22 @@ static void LwipTcpSendTask(void *arg) if (connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr))) { - lw_error("Unable to connect\n"); + KPrintf("Unable to connect\n"); closesocket(fd); return; } - lw_notice("tcp connect success, start to send.\n"); - lw_notice("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); + KPrintf("tcp connect success, start to send.\n"); + KPrintf("\n\nTarget Port:%d\n\n", tcp_sock.sin_port); tcp_send_task_on = 1; - while(tcp_send_num > 0 || tcp_send_num == -1) - { + while(tcp_send_num > 0 || tcp_send_num == -1) { sendto(fd, tcp_demo_msg, strlen(tcp_demo_msg), 0, (struct sockaddr*)&tcp_sock, sizeof(struct sockaddr)); - lw_notice("Send tcp msg: %s \n", tcp_demo_msg); - if(tcp_send_num > 0) - { + KPrintf("Send tcp msg: %s \n", tcp_demo_msg); + if(tcp_send_num > 0) { tcp_send_num--; } - DelayKTask(tcp_interval); + MdelayKTask(tcp_interval); } closesocket(fd); @@ -82,41 +80,39 @@ static void LwipTcpSendTask(void *arg) void LwipTcpSendTest(int argc, char *argv[]) { - if(tcp_send_task_on){ + if(tcp_send_task_on) { tcp_send_num = 0; printf("waitting send task exit...\n"); - while(tcp_send_task_on){ - DelayKTask(1000); + while(tcp_send_task_on) { + MdelayKTask(1000); } tcp_send_num = 1; } LwipTcpSocketParamType param; uint8_t enet_port = 0; memset(tcp_demo_msg, 0, LWIP_TEST_MSG_SIZE); - if(argc >= 2) - { + if(argc >= 2) { strncpy(tcp_demo_msg, argv[1], strlen(argv[1])); - } - else - { + } else { strncpy(tcp_demo_msg, "hello world", strlen("hello world")); + tcp_send_num = 10;//send 10 msg to server + tcp_interval = 100;//100ms } strcat(tcp_demo_msg, "\r\n"); - if(argc >= 3) - { - if(sscanf(argv[2], "%d.%d.%d.%d:%d", &tcp_demo_ip[0], &tcp_demo_ip[1], &tcp_demo_ip[2], &tcp_demo_ip[3], &tcp_demo_port) == EOK) + if(argc >= 3) { + if(sscanf(argv[2], "%d.%d.%d.%d:%d", &tcp_server_ip[0], &tcp_server_ip[1], &tcp_server_ip[2], &tcp_server_ip[3], &tcp_server_port) == EOK) { - sscanf(argv[2], "%d.%d.%d.%d", &tcp_demo_ip[0], &tcp_demo_ip[1], &tcp_demo_ip[2], &tcp_demo_ip[3]); + sscanf(argv[2], "%d.%d.%d.%d", &tcp_server_ip[0], &tcp_server_ip[1], &tcp_server_ip[2], &tcp_server_ip[3]); } sscanf(argv[3], "%d", &tcp_send_num); sscanf(argv[4], "%d", &tcp_interval); } - lw_notice("get ipaddr %d.%d.%d.%d:%d send msg %d times\n", tcp_demo_ip[0], tcp_demo_ip[1], tcp_demo_ip[2], tcp_demo_ip[3], tcp_demo_port, tcp_send_num); - lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, tcp_demo_ip); + KPrintf("connect ipaddr %d.%d.%d.%d:%d send msg %d times\n", tcp_server_ip[0], tcp_server_ip[1], tcp_server_ip[2], tcp_server_ip[3], tcp_server_port, tcp_send_num); + lwip_config_tcp(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - memcpy(param.ip, tcp_demo_ip, 4); - param.port = tcp_demo_port; + memcpy(param.ip, tcp_server_ip, 4); + param.port = tcp_server_port; param.buf = malloc(LWIP_TEST_MSG_SIZE); memcpy(param.buf, tcp_demo_msg, LWIP_TEST_MSG_SIZE); @@ -131,7 +127,96 @@ void LwipTcpRecvTest(void) uint8_t enet_port = 0; ///< test enet port 0 lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - tcpecho_raw_init(); + + uint8_t *recv_data; + socklen_t sin_size; + int sock = -1, connected, bytes_received, i; + struct sockaddr_in server_addr, client_addr; + fd_set readset; + struct timeval timeout; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__); + goto __exit; + } + + recv_data = (uint8_t *)malloc(128); + if (recv_data == NULL) { + KPrintf("No memory!\n"); + goto __exit; + } + + //configure tcp server param + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(tcp_server_port); + server_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); + + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { + KPrintf("Unable to bind!\n"); + goto __exit; + } + + if (listen(sock, 5) == -1){ + KPrintf("Listen error!\n"); + goto __exit; + } + + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { + KPrintf("setsockopt failed!"); + goto __exit; + } + + while (1) { + FD_ZERO(&readset); + FD_SET(sock, &readset); + + if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0) { + continue; + } + + sin_size = sizeof(struct sockaddr_in); + + connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size); + + while (1) { + bytes_received = recv(connected, recv_data, 128, 0); + if (bytes_received == 0) { + KPrintf("client disconnected (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } else if (bytes_received < 0) { + KPrintf("recv error, client: (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } else { + KPrintf("new client connected from (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + KPrintf("recv data length %d Bytes\n", bytes_received); + for (i = 0; i < bytes_received; i ++) { + KPrintf("data 0x%x\n", recv_data[i]); + } + if (i = bytes_received) { + KPrintf("\r\n"); + memset(recv_data, 0, sizeof(recv_data)); + } + } + } + + if (connected >= 0) { + closesocket(connected); + connected = -1; + break; + } + } + +__exit: + if (sock >= 0) closesocket(sock); + if (recv_data) free(recv_data); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_udp_demo.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_udp_demo.c index d7b51b026..a978e773d 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_udp_demo.c +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/lwip_udp_demo.c @@ -19,168 +19,243 @@ */ #include "board.h" #include "sys_arch.h" -#include "lwip/udp.h" -#include "lwip/sockets.h" -#include #include #include +#include +#include + +#include "lwip/sockets.h" +#include "lwip/udp.h" + +#include +#include #define PBUF_SIZE 27 static struct udp_pcb *udpecho_raw_pcb; -char udp_demo_ip[] = {192, 168, 131, 1}; -u16_t udp_demo_port = LWIP_TARGET_PORT; -int32 udp_send_num = 0; -int8 udp_send_task_on = 0; -uint32 udp_interval = 50; - +u16_t udp_server_port = LWIP_TARGET_PORT; +#define UDP_BUFFER_SIZE 50 char hello_str[] = {"hello world\r\n"}; -char udp_demo_msg[] = "\nThis one is UDP package!!!\n"; +char udp_demo_buffer[UDP_BUFFER_SIZE] = { '\0' }; /******************************************************************************/ +enum LwipUdpSendParamEnum { + TARGET_IP = 0, + TARGET_PORT = 'p', + SEND_MESSAGE = 'm', + SEND_NUM = 'n', + SEND_INTERVAL = 'i', +}; + +struct LwipUdpSendParam { + uint32_t num; + uint32_t interval; + uint16_t port; + uint8_t ip[4]; + bool task_on; + bool given_ip; + bool given_port; + bool given_msg; +}; + +struct LwipUdpSendParam* get_udp_test_info() +{ + /* init once and init when used. */ + static struct LwipUdpSendParam g_udp_send_param = { + .interval = 100, + .num = 10, + .port = LWIP_TARGET_PORT, + .ip = { 127, 0, 0, 1 }, + .task_on = false, + .given_ip = false, + .given_port = false, + .given_msg = false, + }; + return &g_udp_send_param; +} + +static const char* const usages[] = { + "UDPSend [--options arg] [-option arg]", + NULL, +}; static void LwipUDPSendTask(void *arg) { int cnt = LWIP_DEMO_TIMES; - lw_print("udp_send_demo start.\n"); + KPrintf("udp_send_demo start.\n"); int socket_fd = -1; socket_fd = socket(AF_INET, SOCK_DGRAM, 0); - if (socket_fd < 0) - { - lw_error("Socket error\n"); + if (socket_fd < 0) { + KPrintf("Socket error\n"); return; } struct sockaddr_in udp_sock; udp_sock.sin_family = AF_INET; - udp_sock.sin_port = htons(udp_demo_port); - udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3])); + udp_sock.sin_port = htons(get_udp_test_info()->port); + udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(get_udp_test_info()->ip[0], get_udp_test_info()->ip[1], get_udp_test_info()->ip[2], get_udp_test_info()->ip[3])); memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero)); - if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) - { - lw_error("Unable to connect\n"); + if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) { + KPrintf("Unable to connect\n"); closesocket(socket_fd); return; } - lw_notice("UDP connect success, start to send.\n"); - lw_notice("\n\nTarget Port:%d\n\n", udp_sock.sin_port); - udp_send_task_on = 1; + KPrintf("UDP connect success, start to send.\n"); + KPrintf("\n\nTarget Port:%d\n\n", udp_sock.sin_port); + get_udp_test_info()->task_on = true; - while(udp_send_num > 0 || udp_send_num == -1) - { - sendto(socket_fd, udp_demo_msg, strlen(udp_demo_msg), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr)); - lw_notice("Send UDP msg: %s \n", udp_demo_msg); - DelayKTask(udp_interval); - udp_send_num--; + while (get_udp_test_info()->num > 0 || get_udp_test_info()->num == -1) { + sendto(socket_fd, udp_demo_buffer, strlen(udp_demo_buffer), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr)); + KPrintf("Send UDP msg: %s \n", udp_demo_buffer); + MdelayKTask(get_udp_test_info()->interval); + get_udp_test_info()->num--; } closesocket(socket_fd); - udp_send_task_on = 0; + get_udp_test_info()->task_on = false; return; } -void *LwipUdpSendTest(int argc, char *argv[]) +static int LwipUdpSend(int argc, char* argv[]) { - if(udp_send_task_on){ - udp_send_num = 0; - printf("waitting send task exit...\n"); - while(udp_send_task_on){ - DelayKTask(1000); - } - udp_send_num = 1; + static char usage_info[] = "Send udp NUM message to IP:PORT with time INTERVAL between each message send."; + static char program_info[] = "UDP SEND TEST DEMO."; + + /* Wait if there are former udp task */ + if (get_udp_test_info()->task_on) { + KPrintf("[%s] Waiting former udp send task to exit.\n"); + } + while (get_udp_test_info()->task_on) { + MdelayKTask(1000); } - uint8_t enet_port = 0; ///< test enet port 0 - memset(udp_demo_msg, 0, sizeof(udp_demo_msg)); + get_udp_test_info()->given_ip = false; + get_udp_test_info()->given_port = false; + get_udp_test_info()->given_msg = false; - if(argc == 1) - { - lw_print("lw: [%s] gw %d.%d.%d.%d:%d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3], udp_demo_port); - strncpy(udp_demo_msg, hello_str, strlen(hello_str)); + /* Parse options */ + char* msg_ptr = NULL; + char* ip_ptr = NULL; + bool is_help = false; + struct argparse_option options[] = { + OPT_HELP(&is_help), + OPT_STRING(SEND_MESSAGE, "message", &msg_ptr, "MESSAGE to send", NULL, 0, 0), + OPT_STRING(TARGET_IP, "ip", &ip_ptr, "target IP to send upd messages", NULL, 0, 0), + OPT_INTEGER(TARGET_PORT, "port", &get_udp_test_info()->port, "target PORT to send udp messages", NULL, 0, 0), + OPT_INTEGER(SEND_NUM, "num", &get_udp_test_info()->num, "send NUM udp messages", NULL, 0, 0), + OPT_INTEGER(SEND_INTERVAL, "interval", &get_udp_test_info()->interval, "time INTERVAL between messages", NULL, 0, 0), + OPT_END(), + }; + + struct argparse argparse; + argparse_init(&argparse, options, usages, 0); + argparse_describe(&argparse, usage_info, program_info); + argc = argparse_parse(&argparse, argc, (const char**)argv); + if (argc < 0) { + KPrintf("Error options.\n"); + return -ERROR; } - else - { - strncpy(udp_demo_msg, argv[1], strlen(argv[1])); - strncat(udp_demo_msg, "\r\n", 2); - if(argc == 3) - { - sscanf(argv[2], "%d.%d.%d.%d:%d", &udp_demo_ip[0], &udp_demo_ip[1], &udp_demo_ip[2], &udp_demo_ip[3], &udp_demo_port); - } - if(argc > 3) - { - sscanf(argv[3], "%d", &udp_send_num); - sscanf(argv[4], "%d", &udp_interval); - } + if (is_help) { + return EOK; } - lw_print("lw: [%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__, udp_demo_ip[0], udp_demo_ip[1], udp_demo_ip[2], udp_demo_ip[3], udp_demo_port, udp_send_num, udp_interval); + // translate string to array + sscanf(ip_ptr, "%d.%d.%d.%d", &get_udp_test_info()->ip[0], &get_udp_test_info()->ip[1], &get_udp_test_info()->ip[2], &get_udp_test_info()->ip[3]); + int msg_len = strlen(msg_ptr); + strncpy(udp_demo_buffer, msg_ptr, msg_len < UDP_BUFFER_SIZE ? msg_len : UDP_BUFFER_SIZE); - lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, udp_demo_ip); + /* start task */ + KPrintf("[%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__, + get_udp_test_info()->ip[0], get_udp_test_info()->ip[1], get_udp_test_info()->ip[2], get_udp_test_info()->ip[3], + get_udp_test_info()->port, + get_udp_test_info()->num, + get_udp_test_info()->interval); + + lwip_config_net(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr); sys_thread_new("udp send", LwipUDPSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO); + return EOK; } -SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(3), - UDPSend, LwipUdpSendTest, UDPSend msg [ip:port [num [interval]]]); - -static void LwipUdpRecvTask(void *arg, struct udp_pcb *upcb, struct pbuf *p, - const ip_addr_t *addr, u16_t port) -{ - int udp_len; - err_t err; - struct pbuf* udp_buf; - - LWIP_UNUSED_ARG(arg); - - if (p == NULL) - { - return; - } - - udp_len = p->tot_len; - lw_notice("Receive data :%dB\r\n", udp_len); - - if(udp_len <= 80) - { - lw_notice("%.*s\r\n", udp_len, (char *)(p->payload)); - } - - udp_buf = pbuf_alloc(PBUF_TRANSPORT, PBUF_SIZE, PBUF_RAM); - - memset(udp_buf->payload, 0, PBUF_SIZE); - - err = pbuf_take(udp_buf, "Client receive success!\r\n", 27); - - /* send received packet back to sender */ - udp_sendto(upcb, udp_buf, addr, port); - - /* free the pbuf */ - pbuf_free(p); - pbuf_free(udp_buf); -} +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(16), + UDPSend, LwipUdpSend, UDPSend Demo); void LwipUdpRecvTest(void) { - err_t err; uint8_t enet_port = 0; ///< test enet port 0 + //init lwip and net dirver lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr); - udpecho_raw_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (udpecho_raw_pcb == NULL) - { - return; + uint8_t *recv_data; + socklen_t sin_size; + int sock = -1, connected, bytes_received, i; + struct sockaddr_in server_addr, client_addr; + fd_set readset; + struct timeval timeout; + + sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__); + goto __exit; } - err = udp_bind(udpecho_raw_pcb, IP_ANY_TYPE, LWIP_LOCAL_PORT); - if (err == ERR_OK) - { - udp_recv(udpecho_raw_pcb, LwipUdpRecvTask, NULL); + recv_data = (uint8_t *)malloc(128); + if (recv_data == NULL) { + KPrintf("No memory!\n"); + goto __exit; } + + //configure udp server param + server_addr.sin_family = PF_INET; + server_addr.sin_port = htons(udp_server_port); + server_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); + + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { + KPrintf("Unable to bind!\n"); + goto __exit; + } + + timeout.tv_sec = 30; + timeout.tv_usec = 0; + + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { + KPrintf("setsockopt failed!"); + goto __exit; + } + + while (1) { + bytes_received = recvfrom(sock, recv_data, 128, 0, (struct sockaddr *)&client_addr, (socklen_t*)&sin_size); + if (bytes_received == 0) { + KPrintf("client disconnected (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } else if (bytes_received < 0) { + KPrintf("recv error, client: (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + break; + } else { + KPrintf("new client connected from (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + KPrintf("recv data length %d Bytes\n", bytes_received); + for (i = 0; i < bytes_received; i ++) { + KPrintf("data 0x%x\n", recv_data[i]); + } + if (i = bytes_received) { + KPrintf("\r\n"); + memset(recv_data, 0, sizeof(recv_data)); + } + } + } + +__exit: + if (sock >= 0) closesocket(sock); + if (recv_data) free(recv_data); } SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(0), diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/Makefile b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/Makefile new file mode 100644 index 000000000..6974c011c --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/Makefile @@ -0,0 +1,4 @@ +SRC_FILES += netdev_register.c netdev_manipulate.c netdev_lowlevel.c + + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c new file mode 100644 index 000000000..c1d4e0fa4 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_lowlevel.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-18 ChenYong First version + */ + +/** +* @file netdev_lowlevel.c +* @brief register low-level net dev function +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +/************************************************* +File name: netdev_lowlevel.c +Description: register low-level net dev function +Others: take RT-Thread v4.0.2/components/driver/serial/serial.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2023-08-07 +Author: AIIT XUOS Lab +Modification: +1. support low-level net dev set-ip, set-netmask, set-gw, set-status, set-link-status, set-dns-server and set-dhcp-status +*************************************************/ + +#include +#include +#include + +/** + * This function will set network interface device IP address. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param ip_addr the new IP address + */ +void netdev_low_level_set_ipaddr(struct netdev* netdev, const ip_addr_t* ip_addr) +{ + CHECK(ip_addr); + + if (netdev && ip_addr_cmp(&(netdev->ip_addr), ip_addr) == 0) { + ip_addr_copy(netdev->ip_addr, *ip_addr); + + /* execute IP address change callback function */ + if (netdev->addr_callback) { + netdev->addr_callback(netdev, NETDEV_CB_ADDR_IP); + } + } +} + +/** + * This function will set network interface device netmask address. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param netmask the new netmask address + */ +void netdev_low_level_set_netmask(struct netdev* netdev, const ip_addr_t* netmask) +{ + CHECK(netmask); + + if (netdev && ip_addr_cmp(&(netdev->netmask), netmask) == 0) { + ip_addr_copy(netdev->netmask, *netmask); + + /* execute netmask address change callback function */ + if (netdev->addr_callback) { + netdev->addr_callback(netdev, NETDEV_CB_ADDR_NETMASK); + } + } +} + +/** + * This function will set network interface device gateway address. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param gw the new gateway address + */ +void netdev_low_level_set_gw(struct netdev* netdev, const ip_addr_t* gw) +{ + CHECK(gw); + + if (netdev && ip_addr_cmp(&(netdev->gw), gw) == 0) { + ip_addr_copy(netdev->gw, *gw); + + /* execute gateway address change callback function */ + if (netdev->addr_callback) { + netdev->addr_callback(netdev, NETDEV_CB_ADDR_GATEWAY); + } + } +} + +/** + * This function will set network interface device DNS server address. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param dns_num the number of the DNS server + * @param dns_server the new DNS server address + * + */ +void netdev_low_level_set_dns_server(struct netdev* netdev, uint8_t dns_num, const ip_addr_t* dns_server) +{ + unsigned int index; + + CHECK(dns_server); + + if (netdev == NULL) { + return; + } + /* check DNS servers is exist */ + for (index = 0; index < NETDEV_DNS_SERVERS_NUM; index++) { + if (ip_addr_cmp(&(netdev->dns_servers[index]), dns_server)) { + return; + } + } + + if (dns_num < NETDEV_DNS_SERVERS_NUM) { + ip_addr_copy(netdev->dns_servers[dns_num], *dns_server); + + /* execute DNS servers address change callback function */ + if (netdev->addr_callback) { + netdev->addr_callback(netdev, NETDEV_CB_ADDR_DNS_SERVER); + } + } +} + +/* Change to the first link_up network interface device automatically */ +static void netdev_auto_change_default(struct netdev* netdev) +{ + struct netdev* new_netdev = NULL; + + if (netdev->flags & NETDEV_FLAG_LINK_UP) { + if (!(NETDEV_DEFAULT->flags & NETDEV_FLAG_LINK_UP)) { + netdev_set_default(netdev); + } + return; + } + if (memcmp(netdev, NETDEV_DEFAULT, sizeof(struct netdev)) == 0) { + new_netdev = netdev_get_first_by_flags(NETDEV_FLAG_LINK_UP); + if (new_netdev) { + netdev_set_default(new_netdev); + } + } +} + +/** + * This function will set network interface device status. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param is_up the new status + */ +void netdev_low_level_set_status(struct netdev* netdev, bool is_up) +{ + if (netdev && netdev_is_up(netdev) != is_up) { + if (is_up) { + netdev->flags |= NETDEV_FLAG_UP; + } else { + netdev->flags &= ~NETDEV_FLAG_UP; + + /* change to the first link_up network interface device automatically */ + netdev_auto_change_default(netdev); + } + + /* execute network interface device status change callback function */ + if (netdev->status_callback) { + netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_UP : NETDEV_CB_STATUS_DOWN); + } + } +} + +/** + * This function will set network interface device active link status. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param is_up the new link status + */ +void netdev_low_level_set_link_status(struct netdev* netdev, bool is_up) +{ + if (netdev && netdev_is_link_up(netdev) != is_up) { + if (is_up) { + netdev->flags |= NETDEV_FLAG_LINK_UP; + } else { + netdev->flags &= ~NETDEV_FLAG_LINK_UP; + + /* set network interface device flags to internet down */ + netdev->flags &= ~NETDEV_FLAG_INTERNET_UP; + + netdev_auto_change_default(netdev); + } + + /* execute link status change callback function */ + if (netdev->status_callback) { + netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_LINK_UP : NETDEV_CB_STATUS_LINK_DOWN); + } + } +} + +/** + * This function will set network interface device active internet status. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param is_up the new internet status + */ +void netdev_low_level_set_internet_status(struct netdev* netdev, bool is_up) +{ + if (netdev && netdev_is_internet_up(netdev) != is_up) { + if (is_up) { + netdev->flags |= NETDEV_FLAG_INTERNET_UP; + } else { + netdev->flags &= ~NETDEV_FLAG_INTERNET_UP; + } + + /* execute network interface device status change callback function */ + if (netdev->status_callback) { + netdev->status_callback(netdev, is_up ? NETDEV_CB_STATUS_INTERNET_UP : NETDEV_CB_STATUS_INTERNET_DOWN); + } + } +} + +/** + * This function will set network interface device DHCP status. + * @NOTE it can only be called in the network interface device driver. + * + * @param netdev the network interface device to change + * @param is_up the new DHCP status + */ +void netdev_low_level_set_dhcp_status(struct netdev* netdev, bool is_enable) +{ + if (netdev && netdev_is_dhcp_enabled(netdev) != is_enable) { + if (is_enable) { + netdev->flags |= NETDEV_FLAG_DHCP; + } else { + netdev->flags &= ~NETDEV_FLAG_DHCP; + } + + /* execute DHCP status change callback function */ + if (netdev->status_callback) { + netdev->status_callback(netdev, is_enable ? NETDEV_CB_STATUS_DHCP_ENABLE : NETDEV_CB_STATUS_DHCP_DISABLE); + } + } +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c new file mode 100644 index 000000000..97e15d3a1 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_manipulate.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-18 ChenYong First version + */ + +/** +* @file netdev_manipulate.c +* @brief register net dev function +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +/************************************************* +File name: netdev_manipulate.c +Description: register net dev function +Others: take RT-Thread v4.0.2/components/driver/serial/serial.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2023-08-07 +Author: AIIT XUOS Lab +Modification: +1. support net dev set-ip, set-netmask, set-gw, set-addr-callback, set-status-callback, set-up and set-down +*************************************************/ + +#include +#include +#include +#include + +inline int netdev_check_set_addr_condition(struct netdev* netdev) +{ + if (NULL == netdev->ops || NULL == netdev->ops->set_addr_info) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The network interface device(%s) not support to set IP address.\n", netdev->name)); + return -ERROR; + } + + // check whether dhcp enabled + if (netdev_is_dhcp_enabled(netdev)) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The network interface device(%s) DHCP capability is enable, not support set IP address.\n", netdev->name)); + return -ERROR; + } + + return EOK; +} + +/** + * This function will set network interface device IP address. + * + * @param netdev the network interface device to change + * @param ip_addr the new IP address + * + * @return 0: set IP address successfully + * -1: set IP address failed + */ +int netdev_set_ipaddr(struct netdev* netdev, const ip_addr_t* ipaddr) +{ + CHECK(netdev); + CHECK(ipaddr); + + if (EOK != netdev_check_set_addr_condition(netdev)) { + return -ERROR; + } + + return netdev->ops->set_addr_info(netdev, (ip_addr_t*)ipaddr, NULL, NULL); +} + +/** + * This function will set network interface device netmask address. + * + * @param netdev the network interface device to change + * @param netmask the new netmask address + * + * @return 0: set netmask address successfully + * -1: set netmask address failed + */ +int netdev_set_netmask(struct netdev* netdev, const ip_addr_t* netmask) +{ + CHECK(netdev); + CHECK(netmask); + + if (EOK != netdev_check_set_addr_condition(netdev)) { + return -ERROR; + } + + return netdev->ops->set_addr_info(netdev, NULL, (ip_addr_t*)netmask, NULL); +} + +/** + * This function will set network interface device gateway address. + * + * @param netdev the network interface device to change + * @param gw the new gateway address + * + * @return 0: set gateway address successfully + * -1: set gateway address failed + */ +int netdev_set_gw(struct netdev* netdev, const ip_addr_t* gw) +{ + CHECK(netdev); + CHECK(gw); + + if (EOK != netdev_check_set_addr_condition(netdev)) { + return -ERROR; + } + + /* execute network interface device set gateway address operations */ + return netdev->ops->set_addr_info(netdev, NULL, NULL, (ip_addr_t*)gw); +} + +/** + * This function will set network interface device DNS server address. + * + * @param netdev the network interface device to change + * @param dns_num the number of the DNS server + * @param dns_server the new DNS server address + * + * @return 0: set netmask address successfully + * -1: set netmask address failed + */ +int netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, const ip_addr_t* dns_server) +{ + CHECK(netdev); + CHECK(dns_server); + + // check dns server number + if (dns_num >= NETDEV_DNS_SERVERS_NUM) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The number of DNS servers(%d) set exceeds the maximum number(%d).\n", dns_num + 1, NETDEV_DNS_SERVERS_NUM)); + return -ERROR; + } + + // check dns set function existence + if (NULL == netdev->ops || NULL == netdev->ops->set_dns_server) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The network interface device(%s) not support to set DNS server address.\n", netdev->name)); + return -ERROR; + } + + return netdev->ops->set_dns_server(netdev, dns_num, (ip_addr_t*)dns_server); +} + +/** + * This function will set callback to be called when the network interface device status has been changed. + * + * @param netdev the network interface device to change + * @param status_callback the callback be called when the status has been changed. + */ +void netdev_set_status_callback(struct netdev* netdev, netdev_callback_fn status_callback) +{ + CHECK(netdev); + CHECK(status_callback); + + netdev->status_callback = status_callback; +} + +/** + * This function will set callback to be called when the network interface device address has been changed. + * + * @param netdev the network interface device to change + * @param addr_callback the callback be called when the address has been changed. + */ +void netdev_set_addr_callback(struct netdev* netdev, netdev_callback_fn addr_callback) +{ + CHECK(netdev); + CHECK(addr_callback); + + netdev->addr_callback = addr_callback; +} + +/** + * This function will enable network interface device . + * + * @param netdev the network interface device to change + * + * @return 0: set status successfully + * -1: set status failed + */ +int netdev_set_up(struct netdev* netdev) +{ + CHECK(netdev); + + if (!netdev->ops || !netdev->ops->set_up) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The network interface device(%s) not support to set status.\n", netdev->name)); + return -ERROR; + } + + /* network interface device status flags check */ + if (netdev_is_up(netdev)) { + return EOK; + } + + /* execute enable network interface device operations by network interface device driver */ + return netdev->ops->set_up(netdev); +} + +/** + * This function will disable network interface device. + * + * @param netdev the network interface device to change + * + * @return 0: set status successfully + * -1: set sttaus failed + */ +int netdev_set_down(struct netdev* netdev) +{ + CHECK(netdev); + + if (!netdev->ops || !netdev->ops->set_down) { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("The network interface device(%s) not support to set status.\n", netdev->name)); + return -ERROR; + } + + /* network interface device status flags check */ + if (!netdev_is_up(netdev)) { + return EOK; + } + + /* execute disable network interface device operations by network interface driver */ + return netdev->ops->set_down(netdev); +} + +/** + * This function will get the first network interface device + * with the flags in network interface device list. + * + * @param flags the network interface device flags + * + * @return != NULL: network interface device object + * NULL: get failed + */ +struct netdev* netdev_get_first_by_flags(uint16_t flags) +{ + if (NETDEV_LISTHEAD == NULL) { + return NULL; + } + + // get netdev from list + x_base lock = DISABLE_INTERRUPT(); + struct netdev* current_dev = NETDEV_LISTHEAD; + SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) + { + if (NULL != current_dev && 0 != (current_dev->flags & flags)) { + ENABLE_INTERRUPT(lock); + return current_dev; + } + } + ENABLE_INTERRUPT(lock); + + return NULL; +} + +/** + * This function will get the first network interface device + * in network interface device list by IP address. + * + * @param ip_addr the network interface device IP address + * + * @return != NULL: network interface device object + * NULL: get failed + */ +struct netdev* netdev_get_by_ipaddr(ip_addr_t* ip_addr) +{ + if (NETDEV_LISTHEAD == NULL) { + return NULL; + } + + // get netdev from list + x_base lock = DISABLE_INTERRUPT(); + struct netdev* current_dev = NETDEV_LISTHEAD; + SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) + { + if (NULL != current_dev && ip_addr_cmp(&(current_dev->ip_addr), ip_addr)) { + ENABLE_INTERRUPT(lock); + return current_dev; + } + } + ENABLE_INTERRUPT(lock); + + return NULL; +} + +/** + * This function will get network interface device + * in network interface device list by netdev name. + * + * @param name the network interface device name + * + * @return != NULL: network interface device object + * NULL: get failed + */ +struct netdev* netdev_get_by_name(const char* name) +{ + if (NETDEV_LISTHEAD == NULL) { + return NULL; + } + + // get netdev from list + x_base lock = DISABLE_INTERRUPT(); + struct netdev* current_dev = NETDEV_LISTHEAD; + SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) + { + if (NULL == current_dev) { + continue; + } + uint32_t name_len = strlen(current_dev->name); + if (NULL != current_dev && (strncmp(current_dev->name, name, strlen(current_dev->name) < NAME_NUM_MAX ? strlen(current_dev->name) : NAME_NUM_MAX) == 0)) { + ENABLE_INTERRUPT(lock); + return current_dev; + } + } + ENABLE_INTERRUPT(lock); + + return NULL; +} diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c new file mode 100644 index 000000000..73ef0ed88 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/netdev/netdev_register.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-03-18 ChenYong First version + */ + +/** +* @file netdev_register.c +* @brief register net dev function for net driver +* @version 3.0 +* @author AIIT XUOS Lab +* @date 2023-08-07 +*/ + +/************************************************* +File name: netdev_register.c +Description: register net dev function for net driver +Others: take RT-Thread v4.0.2/components/driver/serial/serial.c for references + https://github.com/RT-Thread/rt-thread/tree/v4.0.2 +History: +1. Date: 2023-08-07 +Author: AIIT XUOS Lab +Modification: +1. support net dev register, unregister function +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +struct netdev** get_netdev_listhead() +{ + static struct netdev* netdev_listhead = NULL; + return &netdev_listhead; +} +struct netdev** get_default_netdev() +{ + static struct netdev* netdev_default = NULL; + return &netdev_default; +} +static netdev_callback_fn g_netdev_register_callback = NULL; +static netdev_callback_fn g_netdev_default_change_callback = NULL; + +int netdev_register(struct netdev* netdev, const char* name, void* user_data) +{ + CHECK(netdev != NULL); + CHECK(name != NULL); + + // set flag mask, assert network is down + uint16_t flag_mask = 0; + flag_mask = NETDEV_FLAG_UP | NETDEV_FLAG_LINK_UP | NETDEV_FLAG_INTERNET_UP | NETDEV_FLAG_DHCP; + netdev->flags &= ~flag_mask; + + // clear dev setting + ip_addr_set_zero(&(netdev->ip_addr)); + ip_addr_set_zero(&(netdev->netmask)); + ip_addr_set_zero(&(netdev->gw)); + + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->netmask, IPADDR_TYPE_V4); + IP_SET_TYPE_VAL(netdev->gw, IPADDR_TYPE_V4); + +#if NETDEV_IPV6 + for (index = 0; index < NETDEV_IPV6_NUM_ADDRESSES; index++) { + ip_addr_set_zero(&(netdev->ip6_addr[index])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V6); + } +#endif /* NETDEV_IPV6 */ + + // clear DNS servers + for (uint16_t idx = 0; idx < NETDEV_DNS_SERVERS_NUM; idx++) { + ip_addr_set_zero(&(netdev->dns_servers[idx])); + IP_SET_TYPE_VAL(netdev->ip_addr, IPADDR_TYPE_V4); + } + // clear callback fn + netdev->addr_callback = NULL; + netdev->status_callback = NULL; + + // validate name + uint32_t name_len = strlen(name); + if (name_len < NAME_NUM_MAX) { + strncpy(netdev->name, name, name_len); + netdev->name[name_len] = '\0'; + } else { + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] name too long.\n", __func__)); + strncpy(netdev->name, name, NAME_NUM_MAX - 1); + netdev->name[NAME_NUM_MAX - 1] = '\0'; + } + + netdev->user_data = user_data; + + InitSingleLinkList(&(netdev->list)); + + // insert netdev to global list + x_base lock = DISABLE_INTERRUPT(); + if (NETDEV_LISTHEAD == NULL) { + NETDEV_LISTHEAD = netdev; + } else { + SingleLinkListNodeInsert(&(NETDEV_LISTHEAD->list), &(netdev->list)); + } + ENABLE_INTERRUPT(lock); + + if (NETDEV_DEFAULT == NULL) { + // set first met netdev to default netdev + netdev_set_default(NETDEV_LISTHEAD); + } + + if (g_netdev_register_callback) { + g_netdev_register_callback(netdev, NETDEV_CB_REGISTER); + } + + return EOK; +} + +/** + * This function will unregister network interface device and + * delete it from network interface device list. + * + * @param netdev the network interface device object + * + * @return 0: unregistered successfully + * -1: unregistered failed + */ +int netdev_unregister(struct netdev* netdev) +{ + CHECK(netdev); + + if (NETDEV_LISTHEAD == NULL) { + return -ERROR; + } + + // remove netdev from netdev list + x_base lock = DISABLE_INTERRUPT(); + struct netdev* current_dev = NETDEV_LISTHEAD; + SINGLE_LINKLIST_FOR_EACH_ENTRY(current_dev, &(NETDEV_LISTHEAD->list), list) + { + // found netdev in list + if (current_dev == netdev) { + if (NETDEV_LISTHEAD == current_dev && NULL == SingleLinkListGetNextNode(&(current_dev->list))) { + // netdev is the only one in list + NETDEV_LISTHEAD = NULL; + } else { + SingleLinkListRmNode(&(NETDEV_LISTHEAD->list), &(current_dev->list)); + } + + // deal default netdev + if (current_dev == NETDEV_DEFAULT) { + NETDEV_DEFAULT = NULL; + } + break; + } + } + ENABLE_INTERRUPT(lock); + + if (NETDEV_DEFAULT == NULL) { + netdev_set_default(NETDEV_LISTHEAD); + } + + // clean netdev if found one + if (current_dev == netdev) { + memset(netdev, 0, sizeof(*netdev)); + } + + return EOK; +} + +/** + * This function will set default network interface device. + * + * @param netdev the network interface device to change + */ +void netdev_set_default(struct netdev* netdev) +{ + if (netdev && (netdev != NETDEV_DEFAULT)) { + NETDEV_DEFAULT = netdev; + + // set default function + if (netdev->ops && netdev->ops->set_default) { + netdev->ops->set_default(netdev); + } + + // default change callback + if (g_netdev_default_change_callback) { + g_netdev_default_change_callback(netdev, NETDEV_CB_DEFAULT_CHANGE); + } + + SYS_KDEBUG_LOG(NETDEV_DEBUG, ("Setting default network interface device name(%s) successfully.\n", netdev->name)); + } +} + +/** + * This function will set register callback + * + * @param register_callback the network register callback + * + */ +void netdev_set_register_callback(netdev_callback_fn register_callback) +{ + g_netdev_register_callback = register_callback; +} + +void netdev_set_default_change_callback(netdev_callback_fn default_change_cb) +{ + g_netdev_default_change_callback = default_change_cb; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h new file mode 100644 index 000000000..e3007fd9e --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev.h @@ -0,0 +1,181 @@ + +#ifndef __NETDEV_H__ +#define __NETDEV_H__ + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NETDEV_DEBUG_PRINT_IP_INFO(ip, netmask, gw) \ + ("[%s %d]ip: %u.%u.%u.%u, netmask: %u.%u.%u.%u, gw: %u.%u.%u.%u\n", \ + __func__, __LINE__, \ + ((u8_t*)&ip)[0], ((u8_t*)&ip)[1], ((u8_t*)&ip)[2], ((u8_t*)&ip)[3], \ + ((u8_t*)&netmask)[0], ((u8_t*)&netmask)[1], ((u8_t*)&netmask)[2], ((u8_t*)&netmask)[3], \ + ((u8_t*)&gw)[0], ((u8_t*)&gw)[1], ((u8_t*)&gw)[2], ((u8_t*)&gw)[3]) + +/* the maximum of all used hardware address lengths */ +#ifndef NETDEV_HWADDR_MAX_LEN +#define NETDEV_HWADDR_MAX_LEN 8U +#endif + +/* the maximum of dns server number supported */ +#ifndef NETDEV_DNS_SERVERS_NUM +#define NETDEV_DNS_SERVERS_NUM 2U +#endif + +/* whether the network interface device is 'up' (set by the network interface driver or application) */ +#define NETDEV_FLAG_UP 0x01U +/* if set, the network interface device has broadcast capability, only supported in the 'lwIP' stack */ +#define NETDEV_FLAG_BROADCAST 0x02U +/* if set, the network interface device has an active link (set by the network interface driver) */ +#define NETDEV_FLAG_LINK_UP 0x04U +/* if set, the network interface device is an ethernet device using ARP, only supported in the 'lwIP' stack */ +#define NETDEV_FLAG_ETHARP 0x08U +/* if set, the network interface device is an ethernet device, only supported in the 'lwIP' stack */ +#define NETDEV_FLAG_ETHERNET 0x10U +/* if set, the network interface device has IGMP capability, only supported in the 'lwIP' stack */ +#define NETDEV_FLAG_IGMP 0x20U +/* if set, the network interface device has MLD6 capability, only supported in the 'lwIP' stack */ +#define NETDEV_FLAG_MLD6 0x40U +/* if set, the network interface device connected to internet successfully (set by the network interface driver) */ +#define NETDEV_FLAG_INTERNET_UP 0x80U +/* if set, the network interface device has DHCP capability (set by the network interface device driver or application) */ +#define NETDEV_FLAG_DHCP 0x100U + +enum netdev_cb_type { + NETDEV_CB_ADDR_IP, /* IP address */ + NETDEV_CB_ADDR_NETMASK, /* subnet mask */ + NETDEV_CB_ADDR_GATEWAY, /* netmask */ + NETDEV_CB_ADDR_DNS_SERVER, /* dns server */ + NETDEV_CB_STATUS_UP, /* changed to 'up' */ + NETDEV_CB_STATUS_DOWN, /* changed to 'down' */ + NETDEV_CB_STATUS_LINK_UP, /* changed to 'link up' */ + NETDEV_CB_STATUS_LINK_DOWN, /* changed to 'link down' */ + NETDEV_CB_STATUS_INTERNET_UP, /* changed to 'internet up' */ + NETDEV_CB_STATUS_INTERNET_DOWN, /* changed to 'internet down' */ + NETDEV_CB_STATUS_DHCP_ENABLE, /* enable DHCP capability */ + NETDEV_CB_STATUS_DHCP_DISABLE, /* disable DHCP capability */ + NETDEV_CB_REGISTER, /* netdev register */ + NETDEV_CB_DEFAULT_CHANGE, /* netdev default change */ +}; + +struct netdev; +typedef void (*netdev_callback_fn)(struct netdev* netdev, enum netdev_cb_type type); + +struct netdev_ops { + /* set network interface device hardware status operations */ + int (*set_up)(struct netdev* netdev); + int (*set_down)(struct netdev* netdev); + + /* set network interface device address information operations */ + int (*set_addr_info)(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw); + int (*set_dns_server)(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server); + int (*set_dhcp)(struct netdev* netdev, bool is_enabled); + +#ifdef RT_USING_FINSH + /* set network interface device common network interface device operations */ + int (*ping)(struct netdev* netdev, const char* host, size_t data_len, uint32_t timeout, struct netdev_ping_resp* ping_resp); + void (*netstat)(struct netdev* netdev); +#endif + + /* set default network interface device in current network stack*/ + int (*set_default)(struct netdev* netdev); +}; + +/* network interface device object */ +struct netdev { + SysSingleLinklistType list; + + char name[NAME_NUM_MAX]; /* network interface device name */ + ip_addr_t ip_addr; /* IP address */ + ip_addr_t netmask; /* subnet mask */ + ip_addr_t gw; /* gateway */ +#if NETDEV_IPV6 + ip_addr_t ip6_addr[NETDEV_IPV6_NUM_ADDRESSES]; /* array of IPv6 addresses */ +#endif /* NETDEV_IPV6 */ + ip_addr_t dns_servers[NETDEV_DNS_SERVERS_NUM]; /* DNS server */ + uint8_t hwaddr_len; /* hardware address length */ + uint8_t hwaddr[NETDEV_HWADDR_MAX_LEN]; /* hardware address */ + + uint16_t flags; /* network interface device status flag */ + uint16_t mtu; /* maximum transfer unit (in bytes) */ + const struct netdev_ops* ops; /* network interface device operations */ + + netdev_callback_fn status_callback; /* network interface device flags change callback */ + netdev_callback_fn addr_callback; /* network interface device address information change callback */ + +#ifdef RT_USING_SAL + void* sal_user_data; /* user-specific data for SAL */ +#endif /* RT_USING_SAL */ + void* user_data; /* user-specific data */ +}; + +// netdev global list +#define NETDEV_LISTHEAD (*get_netdev_listhead()) +#define NETDEV_DEFAULT (*get_default_netdev()) +extern struct netdev** get_netdev_listhead(); +extern struct netdev** get_default_netdev(); + +// netdev register functions: netdev_register.c +int netdev_register(struct netdev* netdev, const char* name, void* user_data); +int netdev_unregister(struct netdev* netdev); +void netdev_set_default(struct netdev* netdev); +void netdev_set_register_callback(netdev_callback_fn status_callback); +void netdev_set_default_change_callback(netdev_callback_fn default_change_cb); + +// netdev manipulate functions: netdev_manipulate.c +struct netdev* netdev_get_first_by_flags(uint16_t flags); +struct netdev* netdev_get_by_ipaddr(ip_addr_t* ip_addr); +struct netdev* netdev_get_by_name(const char* name); + +int netdev_set_ipaddr(struct netdev* netdev, const ip_addr_t* ipaddr); +int netdev_set_netmask(struct netdev* netdev, const ip_addr_t* netmask); +int netdev_set_gw(struct netdev* netdev, const ip_addr_t* gw); +int netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, const ip_addr_t* dns_server); + +void netdev_set_status_callback(struct netdev* netdev, netdev_callback_fn status_callback); +void netdev_set_addr_callback(struct netdev* netdev, netdev_callback_fn addr_callback); + +/* Set network interface device status */ +int netdev_set_up(struct netdev* netdev); +int netdev_set_down(struct netdev* netdev); +int netdev_dhcp_enabled(struct netdev* netdev, bool is_enabled); + +// low level functions which should only be called by net drivers +void netdev_low_level_set_ipaddr(struct netdev* netdev, const ip_addr_t* ipaddr); +void netdev_low_level_set_netmask(struct netdev* netdev, const ip_addr_t* netmask); +void netdev_low_level_set_gw(struct netdev* netdev, const ip_addr_t* gw); +void netdev_low_level_set_dns_server(struct netdev* netdev, uint8_t dns_num, const ip_addr_t* dns_server); +void netdev_low_level_set_status(struct netdev* netdev, bool is_up); +void netdev_low_level_set_link_status(struct netdev* netdev, bool is_up); +void netdev_low_level_set_internet_status(struct netdev* netdev, bool is_up); +void netdev_low_level_set_dhcp_status(struct netdev* netdev, bool is_enable); + +static inline bool netdev_is_dhcp_enabled(struct netdev* netdev) +{ + return (netdev->flags & NETDEV_FLAG_DHCP) ? true : false; +} +static inline bool netdev_is_up(struct netdev* netdev) +{ + return (netdev->flags & NETDEV_FLAG_UP) ? true : false; +} +static inline bool netdev_is_internet_up(struct netdev* netdev) +{ + return (netdev->flags & NETDEV_FLAG_INTERNET_UP) ? true : false; +} +static inline bool netdev_is_link_up(struct netdev* netdev) +{ + return (netdev->flags & NETDEV_FLAG_LINK_UP) ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev_ipaddr.h b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev_ipaddr.h new file mode 100644 index 000000000..cdc129300 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/include/netdev/netdev_ipaddr.h @@ -0,0 +1,124 @@ + +#ifndef LWIP_HDR_IP4_ADDR_H +#ifndef __NETDEV_IPADDR_H__ +#define __NETDEV_IPADDR_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Currently using netdev ipv4 +#define NETDEV_IPV4 1 + +/* IP address types for use in ip_addr_t.type member */ +enum netdev_ip_addr_type { + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +#if (NETDEV_IPV4 && NETDEV_IPV6) /* Both IPV4 and IPV6 */ +// Todo +#elif NETDEV_IPV4 /* NETDEV_IPV4 */ + +#define IP_SET_TYPE_VAL(ipaddr, iptype) +#define IP_SET_TYPE(ipaddr, iptype) +#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_V4 + +#define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) +#define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) +#define ip_addr_set(dest, src) ip4_addr_set(dest, src) +#define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) +#define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) +#define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) +#define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) + +/* directly map this to the lwip internal functions */ +#define inet_addr(cp) netdev_ipaddr_addr(cp) +#define inet_aton(cp, addr) netdev_ip4addr_aton(cp, (ip4_addr_t*)addr) +#define inet_ntoa(addr) netdev_ip4addr_ntoa((const ip4_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) netdev_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + +#else /* NETDEV_IPV6 */ +// Todo +#endif /* NTDEV_IPV4 && NTDEV_IPV6 */ + +#ifdef NETDEV_IPV4 +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +/** 255.255.255.255 */ +#define IPADDR_NONE ((uint32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((uint32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((uint32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((uint32_t)0xffffffffUL) + +#define IP4ADDR_STRLEN_MAX 16 + +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef uint32_t in_addr_t; +#endif + +struct in_addr { + in_addr_t s_addr; +}; + +typedef struct ip4_addr { + uint32_t addr; +} ip4_addr_t; + +typedef ip4_addr_t ip_addr_t; + +/** Copy IP address - faster than ip4_addr_set: no NULL check */ +static inline void ip4_addr_copy(ip4_addr_t dest_addr, const ip4_addr_t src_addr) +{ + dest_addr.addr = src_addr.addr; +} +static inline bool ip4_addr_cmp(const ip4_addr_t* left_addr, const ip4_addr_t* right_addr) +{ + return left_addr->addr == right_addr->addr; +} +/** Safely copy one IP address to another (src may be NULL) */ +static inline void ip4_addr_set(ip4_addr_t* dest_addr, const ip4_addr_t* src_addr) +{ + dest_addr->addr = (src_addr == NULL) ? 0 : src_addr->addr; +} +/** Set complete address to zero */ +static inline void ip4_addr_set_zero(ip4_addr_t* ip4_addr) +{ + ip4_addr->addr = 0; +} +/** Set address to IPADDR_ANY (no need for htonl()) */ +static inline void ip4_addr_set_any(ip4_addr_t* ipaddr) +{ + ipaddr->addr = IPADDR_ANY; +} +static inline bool ip4_addr_isany_val(const ip4_addr_t ipaddr) +{ + return ipaddr.addr == IPADDR_ANY; +} +static inline bool ip4_addr_isany(const ip4_addr_t* ipaddr) +{ + return ipaddr == NULL || ip4_addr_isany_val(*ipaddr); +} + +#endif + +#ifdef __cplusplus +} +#endif + +#endif +#endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c b/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c index 37396e6ea..156db4ebb 100644 --- a/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c +++ b/Ubiquitous/XiZi_IIoT/resources/serial/dev_serial.c @@ -50,6 +50,7 @@ Modification: #include #include +static int serial_isr_cnt = 0; static DoubleLinklistType serialdev_linklist; static int SerialWorkModeCheck(struct SerialDevParam *serial_dev_param) @@ -138,6 +139,9 @@ static inline int SerialDevIntRead(struct SerialHardwareDevice *serial_dev, stru if (serial_dev->serial_fifo.serial_rx->serial_recv_num == serial_dev->serial_fifo.serial_rx->serial_send_num) { if (RET_FALSE == serial_dev->serial_fifo.serial_rx->serial_rx_full) { CriticalAreaUnLock(lock); + if (0 == serial_isr_cnt) { + KSemaphoreSetValue(serial_dev->haldev.dev_sem, 0); + } break; } } @@ -151,11 +155,13 @@ static inline int SerialDevIntRead(struct SerialHardwareDevice *serial_dev, stru if (RET_TRUE == serial_dev->serial_fifo.serial_rx->serial_rx_full) { serial_dev->serial_fifo.serial_rx->serial_rx_full = RET_FALSE; } + + if (serial_isr_cnt > 0) { + serial_isr_cnt--; + } CriticalAreaUnLock(lock); - //MdelayKTask(20); - *read_data = get_char; read_data++; read_length--; @@ -713,6 +719,10 @@ void SerialSetIsr(struct SerialHardwareDevice *serial_dev, int event) if (serial_dev->haldev.dev_recv_callback) { serial_dev->haldev.dev_recv_callback((void *)serial_dev, serial_rx_length); } + + lock = CriticalAreaLock(); + serial_isr_cnt += 1; + CriticalAreaUnLock(lock); KSemaphoreAbandon(serial_dev->haldev.dev_sem); } diff --git a/Ubiquitous/XiZi_IIoT/tool/shell/Makefile b/Ubiquitous/XiZi_IIoT/tool/shell/Makefile index f45467e4a..d2a8f1357 100644 --- a/Ubiquitous/XiZi_IIoT/tool/shell/Makefile +++ b/Ubiquitous/XiZi_IIoT/tool/shell/Makefile @@ -1,3 +1,4 @@ SRC_DIR := letter-shell +SRC_FILES += argparse.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/tool/shell/argparse.c b/Ubiquitous/XiZi_IIoT/tool/shell/argparse.c new file mode 100644 index 000000000..ed453547a --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/tool/shell/argparse.c @@ -0,0 +1,389 @@ +/** + * Copyright (C) 2012-2015 Yecheng Fu + * All rights reserved. + * + * Use of this source code is governed by a MIT-style license that can be found + * in the LICENSE file. + */ +#include "argparse.h" +#include +#include +#include +#include +#include +#include + +#define OPT_UNSET 1 +#define OPT_LONG (1 << 1) + +static const char* +prefix_skip(const char* str, const char* prefix) +{ + size_t len = strlen(prefix); + return strncmp(str, prefix, len) ? NULL : str + len; +} + +static int +prefix_cmp(const char* str, const char* prefix) +{ + for (;; str++, prefix++) + if (!*prefix) { + return 0; + } else if (*str != *prefix) { + return (unsigned char)*prefix - (unsigned char)*str; + } +} + +static void +argparse_error(struct argparse* self, const struct argparse_option* opt, + const char* reason, int flags) +{ + (void)self; + if (flags & OPT_LONG) { + fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason); + } else { + fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason); + } +} + +#include + +static int +argparse_getvalue(struct argparse* self, const struct argparse_option* opt, + int flags) +{ + const char* s = NULL; + if (!opt->value) + goto skipped; + switch (opt->type) { + case ARGPARSE_OPT_BOOLEAN: + if (flags & OPT_UNSET) { + *(int*)opt->value = *(int*)opt->value - 1; + } else { + *(int*)opt->value = *(int*)opt->value + 1; + } + if (*(int*)opt->value < 0) { + *(int*)opt->value = 0; + } + break; + case ARGPARSE_OPT_BIT: + if (flags & OPT_UNSET) { + *(int*)opt->value &= ~opt->data; + } else { + *(int*)opt->value |= opt->data; + } + break; + case ARGPARSE_OPT_STRING: + if (self->optvalue) { + *(const char**)opt->value = self->optvalue; + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(const char**)opt->value = *++self->argv; + } else { + argparse_error(self, opt, "requires a value", flags); + } + break; + case ARGPARSE_OPT_INTEGER: + errno = 0; + if (self->optvalue) { + *(int*)opt->value = strtol(self->optvalue, (char**)&s, 0); + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(int*)opt->value = strtol(*++self->argv, (char**)&s, 0); + } else { + argparse_error(self, opt, "requires a value", flags); + } + if (errno == ERANGE) + argparse_error(self, opt, "numerical result out of range", flags); + if (s[0] != '\0') // no digits or contains invalid characters + argparse_error(self, opt, "expects an integer value", flags); + break; + case ARGPARSE_OPT_FLOAT: + errno = 0; + if (self->optvalue) { + *(float*)opt->value = strtof(self->optvalue, (char**)&s); + self->optvalue = NULL; + } else if (self->argc > 1) { + self->argc--; + *(float*)opt->value = strtof(*++self->argv, (char**)&s); + } else { + argparse_error(self, opt, "requires a value", flags); + } + if (errno == ERANGE) + argparse_error(self, opt, "numerical result out of range", flags); + if (s[0] != '\0') // no digits or contains invalid characters + argparse_error(self, opt, "expects a numerical value", flags); + break; + default: + assert(0); + } + +skipped: + if (opt->callback) { + return opt->callback(self, opt); + } + return 0; +} + +static void +argparse_options_check(const struct argparse_option* options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + switch (options->type) { + case ARGPARSE_OPT_END: + case ARGPARSE_OPT_BOOLEAN: + case ARGPARSE_OPT_BIT: + case ARGPARSE_OPT_INTEGER: + case ARGPARSE_OPT_FLOAT: + case ARGPARSE_OPT_STRING: + case ARGPARSE_OPT_GROUP: + continue; + default: + fprintf(stderr, "wrong option type: %d", options->type); + break; + } + } +} + +static int +argparse_short_opt(struct argparse* self, const struct argparse_option* options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + if (options->short_name == *self->optvalue) { + self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL; + return argparse_getvalue(self, options, 0); + } + } + return -2; +} + +static int +argparse_long_opt(struct argparse* self, const struct argparse_option* options) +{ + for (; options->type != ARGPARSE_OPT_END; options++) { + const char* rest; + int opt_flags = 0; + if (!options->long_name) + continue; + + rest = prefix_skip(self->argv[0] + 2, options->long_name); + if (!rest) { + // negation disabled? + if (options->flags & OPT_NONEG) { + continue; + } + // only OPT_BOOLEAN/OPT_BIT supports negation + if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) { + continue; + } + + if (prefix_cmp(self->argv[0] + 2, "no-")) { + continue; + } + rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name); + if (!rest) + continue; + opt_flags |= OPT_UNSET; + } + if (*rest) { + if (*rest != '=') + continue; + self->optvalue = rest + 1; + } + return argparse_getvalue(self, options, opt_flags | OPT_LONG); + } + return -2; +} + +int argparse_init(struct argparse* self, struct argparse_option* options, + const char* const* usages, int flags) +{ + memset(self, 0, sizeof(*self)); + self->options = options; + self->usages = usages; + self->flags = flags; + self->description = NULL; + self->epilog = NULL; + return 0; +} + +void argparse_describe(struct argparse* self, const char* description, + const char* epilog) +{ + self->description = description; + self->epilog = epilog; +} + +int argparse_parse(struct argparse* self, int argc, const char** argv) +{ + self->argc = argc - 1; + self->argv = argv + 1; + self->out = argv; + + argparse_options_check(self->options); + + for (; self->argc; self->argc--, self->argv++) { + const char* arg = self->argv[0]; + if (arg[0] != '-' || !arg[1]) { + if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) { + goto end; + } + // if it's not option or is a single char '-', copy verbatim + self->out[self->cpidx++] = self->argv[0]; + continue; + } + // short option + if (arg[1] != '-') { + self->optvalue = arg + 1; + switch (argparse_short_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + while (self->optvalue) { + switch (argparse_short_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + } + continue; + } + // if '--' presents + if (!arg[2]) { + self->argc--; + self->argv++; + break; + } + // long option + switch (argparse_long_opt(self, self->options)) { + case -1: + break; + case -2: + goto unknown; + } + continue; + + unknown: + fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]); + argparse_usage(self); + if (!(self->flags & ARGPARSE_IGNORE_UNKNOWN_ARGS)) { + return ARGPARSE_ERROR; + } + } + +end: + memmove(self->out + self->cpidx, self->argv, + self->argc * sizeof(*self->out)); + self->out[self->cpidx + self->argc] = NULL; + + return self->cpidx + self->argc; +} + +void argparse_usage(struct argparse* self) +{ + if (self->usages) { + fprintf(stdout, "Usage: %s\n", *self->usages++); + while (*self->usages && **self->usages) + fprintf(stdout, " or: %s\n", *self->usages++); + } else { + fprintf(stdout, "Usage:\n"); + } + + // print description + if (self->description) + fprintf(stdout, "%s\n", self->description); + + fputc('\n', stdout); + + const struct argparse_option* options; + + // figure out best width + size_t usage_opts_width = 0; + size_t len; + options = self->options; + for (; options->type != ARGPARSE_OPT_END; options++) { + len = 0; + if ((options)->short_name) { + len += 2; + } + if ((options)->short_name && (options)->long_name) { + len += 2; // separator ", " + } + if ((options)->long_name) { + len += strlen((options)->long_name) + 2; + } + if (options->type == ARGPARSE_OPT_INTEGER) { + len += strlen("="); + } + if (options->type == ARGPARSE_OPT_FLOAT) { + len += strlen("="); + } else if (options->type == ARGPARSE_OPT_STRING) { + len += strlen("="); + } + len = (len + 3) - ((len + 3) & 3); + if (usage_opts_width < len) { + usage_opts_width = len; + } + } + usage_opts_width += 4; // 4 spaces prefix + + options = self->options; + for (; options->type != ARGPARSE_OPT_END; options++) { + size_t pos = 0; + size_t pad = 0; + if (options->type == ARGPARSE_OPT_GROUP) { + fputc('\n', stdout); + fprintf(stdout, "%s", options->help); + fputc('\n', stdout); + continue; + } + pos = fprintf(stdout, " "); + if (options->short_name) { + pos += fprintf(stdout, "-%c", options->short_name); + } + if (options->long_name && options->short_name) { + pos += fprintf(stdout, ", "); + } + if (options->long_name) { + pos += fprintf(stdout, "--%s", options->long_name); + } + if (options->type == ARGPARSE_OPT_INTEGER) { + pos += fprintf(stdout, "="); + } else if (options->type == ARGPARSE_OPT_FLOAT) { + pos += fprintf(stdout, "="); + } else if (options->type == ARGPARSE_OPT_STRING) { + pos += fprintf(stdout, "="); + } + if (pos <= usage_opts_width) { + pad = usage_opts_width - pos; + } else { + fputc('\n', stdout); + pad = usage_opts_width; + } + fprintf(stdout, "%*s%s\n", (int)pad + 2, "", options->help); + } + + // print epilog + if (self->epilog) + fprintf(stdout, "%s\n", self->epilog); +} + +int argparse_help_cb_no_exit(struct argparse* self, + const struct argparse_option* option) +{ + (void)option; + argparse_usage(self); + return 0; +} + +int argparse_help_cb(struct argparse* self, const struct argparse_option* option) +{ + argparse_help_cb_no_exit(self, option); + *(bool*)option->value = true; + return 0; +} diff --git a/Ubiquitous/XiZi_IIoT/tool/shell/argparse.h b/Ubiquitous/XiZi_IIoT/tool/shell/argparse.h new file mode 100644 index 000000000..2ccf51b04 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/tool/shell/argparse.h @@ -0,0 +1,157 @@ +/** + * Copyright (C) 2012-2015 Yecheng Fu + * All rights reserved. + * + * Use of this source code is governed by a MIT-style license that can be found + * in the LICENSE file. + */ +#ifndef ARGPARSE_H +#define ARGPARSE_H + +/* For c++ compatibility */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define ARGPARSE_HELP_DONE -1 +#define ARGPARSE_ERROR -2 + +struct argparse; +struct argparse_option; + +typedef int argparse_callback(struct argparse* self, + const struct argparse_option* option); + +enum argparse_flag { + ARGPARSE_STOP_AT_NON_OPTION = 1 << 0, + ARGPARSE_IGNORE_UNKNOWN_ARGS = 1 << 1, +}; + +enum argparse_option_type { + /* special */ + ARGPARSE_OPT_END, + ARGPARSE_OPT_GROUP, + /* options with no arguments */ + ARGPARSE_OPT_BOOLEAN, + ARGPARSE_OPT_BIT, + /* options with arguments (optional or required) */ + ARGPARSE_OPT_INTEGER, + ARGPARSE_OPT_FLOAT, + ARGPARSE_OPT_STRING, +}; + +enum argparse_option_flags { + OPT_NONEG = 1, /* disable negation */ +}; + +/** + * argparse option + * + * `type`: + * holds the type of the option, you must have an ARGPARSE_OPT_END last in your + * array. + * + * `short_name`: + * the character to use as a short option name, '\0' if none. + * + * `long_name`: + * the long option name, without the leading dash, NULL if none. + * + * `value`: + * stores pointer to the value to be filled. + * + * `help`: + * the short help message associated to what the option does. + * Must never be NULL (except for ARGPARSE_OPT_END). + * + * `callback`: + * function is called when corresponding argument is parsed. + * + * `data`: + * associated data. Callbacks can use it like they want. + * + * `flags`: + * option flags. + */ +struct argparse_option { + enum argparse_option_type type; + const char short_name; + const char* long_name; + void* value; + const char* help; + argparse_callback* callback; + intptr_t data; + int flags; +}; + +/** + * argpparse + */ +struct argparse { + // user supplied + const struct argparse_option* options; + const char* const* usages; + int flags; + const char* description; // a description after usage + const char* epilog; // a description at the end + // internal context + int argc; + const char** argv; + const char** out; + int cpidx; + const char* optvalue; // current option value +}; + +// built-in callbacks +int argparse_help_cb(struct argparse* self, + const struct argparse_option* option); +int argparse_help_cb_no_exit(struct argparse* self, + const struct argparse_option* option); + +// built-in option macros +#define OPT_END() \ + { \ + ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 \ + } +#define OPT_BOOLEAN(...) \ + { \ + ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ \ + } +#define OPT_BIT(...) \ + { \ + ARGPARSE_OPT_BIT, __VA_ARGS__ \ + } +#define OPT_INTEGER(...) \ + { \ + ARGPARSE_OPT_INTEGER, __VA_ARGS__ \ + } +#define OPT_FLOAT(...) \ + { \ + ARGPARSE_OPT_FLOAT, __VA_ARGS__ \ + } +#define OPT_STRING(...) \ + { \ + ARGPARSE_OPT_STRING, __VA_ARGS__ \ + } +#define OPT_GROUP(h) \ + { \ + ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 \ + } +#define OPT_HELP(flag) OPT_BOOLEAN('h', "help", flag, \ + "show this help message and exit", \ + argparse_help_cb, 0, OPT_NONEG) + +int argparse_init(struct argparse* self, struct argparse_option* options, + const char* const* usages, int flags); +void argparse_describe(struct argparse* self, const char* description, + const char* epilog); +int argparse_parse(struct argparse* self, int argc, const char** argv); +void argparse_usage(struct argparse* self); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file