Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into micro_kernel
|
@ -29,3 +29,6 @@
|
||||||
path = APP_Framework/lib/lorawan/lorawan_devicenode
|
path = APP_Framework/lib/lorawan/lorawan_devicenode
|
||||||
url = https://gitlink.org.cn/IACU/lorawan_devicenode.git
|
url = https://gitlink.org.cn/IACU/lorawan_devicenode.git
|
||||||
branch = master
|
branch = master
|
||||||
|
[submodule "APP_Framework/lib/lorawan/lorawan_gateway_single_channel"]
|
||||||
|
path = APP_Framework/lib/lorawan/lorawan_gateway_single_channel
|
||||||
|
url = https://gitlink.org.cn/IACU/lorawan_gateway_single_channel.git
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS +=
|
CSRCS +=
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_DIR := general_functions app_test
|
SRC_DIR := general_functions app_test
|
||||||
|
|
||||||
SRC_FILES := main.c
|
SRC_FILES := main.c
|
||||||
|
@ -36,5 +36,9 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
||||||
SRC_DIR += control_app
|
SRC_DIR += control_app
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_APP_USING_WEBNET),y)
|
||||||
|
SRC_DIR += webnet
|
||||||
|
endif
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
endif
|
endif
|
|
@ -8,7 +8,7 @@ menu "test app"
|
||||||
bool "Config test adc"
|
bool "Config test adc"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_ADC
|
if USER_TEST_ADC
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config ADC_DEV_DRIVER
|
config ADC_DEV_DRIVER
|
||||||
string "Set ADC dev path"
|
string "Set ADC dev path"
|
||||||
default "/dev/adc1_dev"
|
default "/dev/adc1_dev"
|
||||||
|
@ -19,7 +19,7 @@ menu "test app"
|
||||||
bool "Config test dac"
|
bool "Config test dac"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_DAC
|
if USER_TEST_DAC
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config DAC_DEV_DRIVER
|
config DAC_DEV_DRIVER
|
||||||
string "Set DAC dev path"
|
string "Set DAC dev path"
|
||||||
default "/dev/dac_dev"
|
default "/dev/dac_dev"
|
||||||
|
@ -30,7 +30,7 @@ menu "test app"
|
||||||
bool "Config test fs with sd or usb"
|
bool "Config test fs with sd or usb"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_FS
|
if USER_TEST_FS
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config FPATH
|
config FPATH
|
||||||
string "Set test file path"
|
string "Set test file path"
|
||||||
default "/test_file"
|
default "/test_file"
|
||||||
|
@ -46,7 +46,7 @@ menu "test app"
|
||||||
bool "Config test gpio with led and key"
|
bool "Config test gpio with led and key"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_GPIO
|
if USER_TEST_GPIO
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config GPIO_DEV_DRIVER
|
config GPIO_DEV_DRIVER
|
||||||
string "Set gpio dev path"
|
string "Set gpio dev path"
|
||||||
default "/dev/pin_dev"
|
default "/dev/pin_dev"
|
||||||
|
@ -62,7 +62,7 @@ menu "test app"
|
||||||
bool "Config test uart(loraE220)"
|
bool "Config test uart(loraE220)"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_LORA
|
if USER_TEST_LORA
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config LORA_UART_DEV_DRIVER
|
config LORA_UART_DEV_DRIVER
|
||||||
string "Set uart dev path"
|
string "Set uart dev path"
|
||||||
default "/dev/uart2_dev2"
|
default "/dev/uart2_dev2"
|
||||||
|
@ -72,6 +72,24 @@ menu "test app"
|
||||||
endif
|
endif
|
||||||
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
|
menuconfig USER_TEST_RS485
|
||||||
select BSP_USING_UART
|
select BSP_USING_UART
|
||||||
select BSP_USING_GPIO
|
select BSP_USING_GPIO
|
||||||
|
@ -80,7 +98,7 @@ menu "test app"
|
||||||
bool "Config test uart(RS485)"
|
bool "Config test uart(RS485)"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_RS485
|
if USER_TEST_RS485
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config RS485_UART_DEV_DRIVER
|
config RS485_UART_DEV_DRIVER
|
||||||
string "Set uart dev path"
|
string "Set uart dev path"
|
||||||
default "/dev/uart1_dev1"
|
default "/dev/uart1_dev1"
|
||||||
|
@ -95,7 +113,7 @@ menu "test app"
|
||||||
bool "Config test rtc"
|
bool "Config test rtc"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_RTC
|
if USER_TEST_RTC
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config RTC_DEV_DRIVER
|
config RTC_DEV_DRIVER
|
||||||
string "Set rtc dev path"
|
string "Set rtc dev path"
|
||||||
default "/dev/rtc_dev"
|
default "/dev/rtc_dev"
|
||||||
|
@ -110,7 +128,7 @@ menu "test app"
|
||||||
bool "Config test hwtimer"
|
bool "Config test hwtimer"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_HWTIMER
|
if USER_TEST_HWTIMER
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config HWTIMER_TIMER_DEV_DRIVER
|
config HWTIMER_TIMER_DEV_DRIVER
|
||||||
string "Set pin dev path"
|
string "Set pin dev path"
|
||||||
default "/dev/timer0_dev0"
|
default "/dev/timer0_dev0"
|
||||||
|
@ -125,7 +143,7 @@ menu "test app"
|
||||||
bool "Config test watchdog"
|
bool "Config test watchdog"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_WDT
|
if USER_TEST_WDT
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config WDT0_DEV_DRIVER
|
config WDT0_DEV_DRIVER
|
||||||
string "Set wdt dev path"
|
string "Set wdt dev path"
|
||||||
default "/dev/wdt0_dev0"
|
default "/dev/wdt0_dev0"
|
||||||
|
@ -137,7 +155,7 @@ menu "test app"
|
||||||
bool "Config test lcd in PrivOpen"
|
bool "Config test lcd in PrivOpen"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_LCD_EDU
|
if USER_TEST_LCD_EDU
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config EDU_LCD_DEV_DRIVER
|
config EDU_LCD_DEV_DRIVER
|
||||||
string "Set lcd dev path"
|
string "Set lcd dev path"
|
||||||
default "/dev/lcd_dev"
|
default "/dev/lcd_dev"
|
||||||
|
@ -149,7 +167,7 @@ menu "test app"
|
||||||
bool "Config test touch"
|
bool "Config test touch"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_TOUCH
|
if USER_TEST_TOUCH
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config TOUCH_DEV_DRIVER
|
config TOUCH_DEV_DRIVER
|
||||||
string "Set touch dev path"
|
string "Set touch dev path"
|
||||||
default "/dev/touch_dev"
|
default "/dev/touch_dev"
|
||||||
|
@ -164,7 +182,7 @@ menu "test app"
|
||||||
bool "Config test i2c"
|
bool "Config test i2c"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_I2C
|
if USER_TEST_I2C
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config I2C_DEV_DRIVER
|
config I2C_DEV_DRIVER
|
||||||
string "Set i2c dev path"
|
string "Set i2c dev path"
|
||||||
default "/dev/i2c1_dev0"
|
default "/dev/i2c1_dev0"
|
||||||
|
@ -176,7 +194,7 @@ menu "test app"
|
||||||
bool "Config test can"
|
bool "Config test can"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_CAN
|
if USER_TEST_CAN
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config CAN_DEV_DRIVER
|
config CAN_DEV_DRIVER
|
||||||
string "Set can dev path"
|
string "Set can dev path"
|
||||||
default "/dev/can2_dev1"
|
default "/dev/can2_dev1"
|
||||||
|
@ -189,7 +207,7 @@ menu "test app"
|
||||||
bool "Config test camera with lcd"
|
bool "Config test camera with lcd"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_CAMERA
|
if USER_TEST_CAMERA
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config CAMERA_DEV_DRIVER
|
config CAMERA_DEV_DRIVER
|
||||||
string "Set camera dev path"
|
string "Set camera dev path"
|
||||||
default "/dev/camera_dev"
|
default "/dev/camera_dev"
|
||||||
|
@ -211,7 +229,7 @@ menu "test app"
|
||||||
bool "Config test ethernet only for edu-riscv64"
|
bool "Config test ethernet only for edu-riscv64"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_ETHERNET
|
if USER_TEST_ETHERNET
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
choice
|
choice
|
||||||
prompt "set ethernet role as client or server"
|
prompt "set ethernet role as client or server"
|
||||||
default ETHERNET_AS_SERVER
|
default ETHERNET_AS_SERVER
|
||||||
|
@ -229,7 +247,7 @@ menu "test app"
|
||||||
bool "Config test w25q128 device"
|
bool "Config test w25q128 device"
|
||||||
default n
|
default n
|
||||||
if USER_TEST_FLASH
|
if USER_TEST_FLASH
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config FLASH_DEV_DRIVER
|
config FLASH_DEV_DRIVER
|
||||||
string "Set flash dev path"
|
string "Set flash dev path"
|
||||||
default "/dev/qspi_W25Q128"
|
default "/dev/qspi_W25Q128"
|
||||||
|
@ -240,5 +258,45 @@ menu "test app"
|
||||||
bool "Config test soft timer"
|
bool "Config test soft timer"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_HASH
|
||||||
|
bool "Config test hash"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_RADIX
|
||||||
|
bool "Config test radix tree"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_RBTREE
|
||||||
|
bool "Config test red black tree"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_WEBSERVER
|
||||||
|
bool "Config test webserver"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_MQTTCLIENT
|
||||||
|
bool "Config test mqtt client"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_FTPCLIENT
|
||||||
|
bool "Config test ftp client"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_LORA_P2P
|
||||||
|
bool "Config test lora p2p"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_LORAWAN_SINGLEGW
|
||||||
|
bool "Config test lorawan single channel gateway"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_CANOPEN
|
||||||
|
bool "Config test CanOpen"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_USB_CAMERA
|
||||||
|
bool "Config test usb camera"
|
||||||
|
default n
|
||||||
|
|
||||||
endif
|
endif
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_SEMC),y)
|
ifeq ($(CONFIG_USER_TEST_SEMC),y)
|
||||||
|
@ -22,7 +22,7 @@ ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := test_shell.c
|
SRC_FILES := test_shell.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_ADC),y)
|
ifeq ($(CONFIG_USER_TEST_ADC),y)
|
||||||
|
@ -49,6 +49,10 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
||||||
SRC_FILES += test_i2c.c
|
SRC_FILES += test_i2c.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_UART),y)
|
||||||
|
SRC_FILES += test_uart.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_GPIO),y)
|
ifeq ($(CONFIG_USER_TEST_GPIO),y)
|
||||||
SRC_FILES += test_gpio.c
|
SRC_FILES += test_gpio.c
|
||||||
endif
|
endif
|
||||||
|
@ -101,5 +105,49 @@ ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
||||||
SRC_FILES += test_timer.c
|
SRC_FILES += test_timer.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_HASH),y)
|
||||||
|
SRC_FILES += test_hash/test_hash.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_RADIX),y)
|
||||||
|
SRC_FILES += test_radix_tree/test_radix_tree.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
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_WEBSERVER),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_MQTTCLIENT),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_FTPCLIENT),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_LORA_P2P),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_LORAWAN_SINGLEGW),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_CANOPEN),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_USB_CAMERA),y)
|
||||||
|
SRC_FILES +=
|
||||||
|
endif
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -21,14 +21,13 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestAdc(void)
|
void TestAdc(void)
|
||||||
{
|
{
|
||||||
int adc_fd;
|
int adc_fd;
|
||||||
uint8 adc_channel = 0x0;
|
uint8 adc_channel = 0x1;
|
||||||
uint16 adc_sample, adc_value_decimal = 0;
|
uint16 adc_sample = 0;
|
||||||
float adc_value;
|
|
||||||
|
|
||||||
adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR);
|
adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR);
|
||||||
if (adc_fd < 0) {
|
if (adc_fd < 0) {
|
||||||
|
@ -45,13 +44,11 @@ void TestAdc(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
PrivRead(adc_fd, &adc_sample, 2);
|
PrivRead(adc_fd, &adc_sample, 2);
|
||||||
|
printf("adc sample %u mv\n", adc_sample);
|
||||||
adc_value = (float)adc_sample * (3.3 / 4096);
|
PrivTaskDelay(500);
|
||||||
|
}
|
||||||
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);
|
|
||||||
|
|
||||||
PrivClose(adc_fd);
|
PrivClose(adc_fd);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
static uint16_t image_buff[384000];
|
static uint16_t image_buff[384000];
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
|
|
||||||
void TestCAN(void)
|
void TestCAN(void)
|
||||||
|
|
|
@ -20,19 +20,18 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestDac(void)
|
static pthread_t test_dac_task;
|
||||||
|
|
||||||
|
static void *TestDacTask(void *parameter)
|
||||||
{
|
{
|
||||||
int dac_fd;
|
int dac_fd;
|
||||||
uint16 dac_set_value = 800;
|
uint16 dac_set_value = 4096 * 10;//sin length
|
||||||
uint16 dac_sample, dac_value_decimal = 0;
|
|
||||||
float dac_value;
|
|
||||||
|
|
||||||
dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR);
|
dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR);
|
||||||
if (dac_fd < 0) {
|
if (dac_fd < 0) {
|
||||||
KPrintf("open dac fd error %d\n", dac_fd);
|
KPrintf("open dac fd error %d\n", dac_fd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PrivIoctlCfg ioctl_cfg;
|
struct PrivIoctlCfg ioctl_cfg;
|
||||||
|
@ -41,20 +40,24 @@ void TestDac(void)
|
||||||
if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) {
|
if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) {
|
||||||
KPrintf("ioctl dac fd error %d\n", dac_fd);
|
KPrintf("ioctl dac fd error %d\n", dac_fd);
|
||||||
PrivClose(dac_fd);
|
PrivClose(dac_fd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivRead(dac_fd, &dac_sample, 2);
|
while (1) {
|
||||||
|
//start dac output sin
|
||||||
dac_value = (float)dac_sample * (3.3 / 4096);//Vref+ need to be 3.3V
|
PrivWrite(dac_fd, NULL, 0);
|
||||||
|
}
|
||||||
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);
|
|
||||||
|
|
||||||
PrivClose(dac_fd);
|
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);
|
PRIV_SHELL_CMD_FUNCTION(TestDac, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
#endif
|
#endif
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#include <socket.h>
|
#include <socket.h>
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestFlash(void)
|
void TestFlash(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define MAX_READ_LENGTH 1000
|
#define MAX_READ_LENGTH 1000
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#ifdef BOARD_EDU_RISCV64_EVB
|
#ifdef BOARD_EDU_RISCV64_EVB
|
||||||
#define BSP_LED_PIN 29
|
#define BSP_LED_PIN 29
|
||||||
#define BSP_KEY_PIN 31
|
#define BSP_KEY_PIN 31
|
||||||
#elif defined BOARD_HC32F4A0_EVB
|
#elif defined BOARD_EDU_ARM32_EVB
|
||||||
#define BSP_LED_PIN 134
|
#define BSP_LED_PIN 134
|
||||||
#define BSP_KEY_PIN 176
|
#define BSP_KEY_PIN 176
|
||||||
#endif
|
#endif
|
||||||
|
|
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 102 KiB |
|
@ -0,0 +1,58 @@
|
||||||
|
# 基于cortex-m3-emulator实现哈希表并测试验证##
|
||||||
|
|
||||||
|
## 1. 简介
|
||||||
|
利用c语言实现了哈希表(HashMap),包括添加键值对(Put),获取键对应的值(Get), 删除健(Delete),清空哈希表(Clear), 迭代遍历哈希表(hashMapIterator)等功能
|
||||||
|
操作。
|
||||||
|
|
||||||
|
利用数组(Entry)作为存储空间,利用链表(*next)解决冲突。当哈希表的大小超过数组大小后,为避免发生冲突过多的情况,可以对哈希表扩容。
|
||||||
|
|
||||||
|
## 2. 数据结构设计说明
|
||||||
|
键值对结构
|
||||||
|
typedef struct entry {
|
||||||
|
void * key; // 键
|
||||||
|
void * value; // 值
|
||||||
|
struct entry * next; // 冲突链表
|
||||||
|
}*Entry;
|
||||||
|
|
||||||
|
哈希结构
|
||||||
|
typedef struct hashMap {
|
||||||
|
int size; // 当前大小
|
||||||
|
int listSize; // 有效空间大小
|
||||||
|
HashCode hashCode; // 哈希函数
|
||||||
|
Equal equal; // 判等函数
|
||||||
|
Entry list; // 存储区域
|
||||||
|
Put put; // 添加键的函数
|
||||||
|
Get get; // 获取键对应值的函数
|
||||||
|
Remove remove; // 删除键
|
||||||
|
Clear clear; // 清空Map
|
||||||
|
Exists exists; // 判断键是否存在
|
||||||
|
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
|
||||||
|
}*HashMap;
|
||||||
|
|
||||||
|
包括以下函数功能,分别为:
|
||||||
|
`createHashMap`:创建一个哈希结构
|
||||||
|
`defaultPut`:添加键值对
|
||||||
|
`defaultGet`:获取键对应值
|
||||||
|
`defaultRemove`:删除指定键的键值对
|
||||||
|
`defaultExists`:判断键值是否存在
|
||||||
|
`defaultClear`:清空Map的函数类型
|
||||||
|
`resetHashMap`:重新构建哈希表
|
||||||
|
|
||||||
|
|
||||||
|
## 3. 测试程序说明
|
||||||
|
测试了哈希表的插入键值对(Put),判断键是否存在(Exist),获取键对应的值(Get), 删除健(Delete),迭代遍历哈希表(hashMapIterator),清空哈希表(Clear)等操作。
|
||||||
|
并展示了利用链地址法解决哈希冲突的示例, 两个不同的人(Bob和Li Ming)的hashcode相同。
|
||||||
|
|
||||||
|
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||||
|

|
||||||
|
打开menuconfig之后,将test_hash_map开启(y),保存后退出
|
||||||
|
|
||||||
|

|
||||||
|
编译XiZi-cortex-m3-emulator.elf成功
|
||||||
|
|
||||||
|

|
||||||
|
启动qemu模拟Xiuos操作系统,验证TestHash注册Shell命令
|
||||||
|
|
||||||
|

|
||||||
|
执行TestHash命令,打印测试结果。
|
||||||
|
|
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 95 KiB |
|
@ -0,0 +1,323 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file: test_hash.c
|
||||||
|
* @brief: a application of test hash function
|
||||||
|
* @version: 3.0
|
||||||
|
* @author: Yao wenying
|
||||||
|
* @date: 2023/05/26
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <transform.h>
|
||||||
|
#include"test_hash.h"
|
||||||
|
|
||||||
|
int defaultHashCode(HashMap hashMap, let key) {
|
||||||
|
char * k = (char *)key;
|
||||||
|
unsigned long h = 0;
|
||||||
|
while (*k) {
|
||||||
|
h = (h << 4) + *k++;
|
||||||
|
unsigned long g = h & 0xF0000000L;
|
||||||
|
if (g) {
|
||||||
|
h ^= g >> 24;
|
||||||
|
}
|
||||||
|
h &= ~g;
|
||||||
|
}
|
||||||
|
return h % hashMap->listSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean defaultEqual(let key1, let key2) {
|
||||||
|
return strcmp((string)key1, (string)key2) ? False : True;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetHashMap(HashMap hashMap, int listSize) {
|
||||||
|
|
||||||
|
if (listSize < 8) return;
|
||||||
|
|
||||||
|
// 键值对临时存储空间
|
||||||
|
Entry tempList = newEntryList(hashMap->size);
|
||||||
|
|
||||||
|
HashMapIterator iterator = createHashMapIterator(hashMap);
|
||||||
|
int length = hashMap->size;
|
||||||
|
for (int index = 0; hasNextHashMapIterator(iterator); index++) {
|
||||||
|
// 迭代取出所有键值对
|
||||||
|
iterator = nextHashMapIterator(iterator);
|
||||||
|
tempList[index].key = iterator->entry->key;
|
||||||
|
tempList[index].value = iterator->entry->value;
|
||||||
|
tempList[index].next = NULL;
|
||||||
|
}
|
||||||
|
freeHashMapIterator(&iterator);
|
||||||
|
|
||||||
|
// 清除原有键值对数据
|
||||||
|
hashMap->size = 0;
|
||||||
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
|
Entry current = &hashMap->list[i];
|
||||||
|
current->key = NULL;
|
||||||
|
current->value = NULL;
|
||||||
|
if (current->next != NULL) {
|
||||||
|
while (current->next != NULL) {
|
||||||
|
Entry temp = current->next->next;
|
||||||
|
free(current->next);
|
||||||
|
current->next = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更改内存大小
|
||||||
|
hashMap->listSize = listSize;
|
||||||
|
Entry relist = (Entry)realloc(hashMap->list, hashMap->listSize * sizeof(struct entry));
|
||||||
|
if (relist != NULL) {
|
||||||
|
hashMap->list = relist;
|
||||||
|
relist = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
|
hashMap->list[i].key = NULL;
|
||||||
|
hashMap->list[i].value = NULL;
|
||||||
|
hashMap->list[i].next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将所有键值对重新写入内存
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
hashMap->put(hashMap, tempList[i].key, tempList[i].value);
|
||||||
|
}
|
||||||
|
free(tempList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void defaultPut(HashMap hashMap, let key, let value) {
|
||||||
|
// 获取哈希值
|
||||||
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
|
|
||||||
|
if (hashMap->list[index].key == NULL) {
|
||||||
|
hashMap->size++;
|
||||||
|
// 该地址为空时直接存储
|
||||||
|
hashMap->list[index].key = key;
|
||||||
|
hashMap->list[index].value = value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
Entry current = &hashMap->list[index];
|
||||||
|
while (current != NULL) {
|
||||||
|
if (hashMap->equal(key, current->key)) {
|
||||||
|
// 对于键值已经存在的直接覆盖
|
||||||
|
current->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 发生冲突则创建节点挂到相应位置的next上
|
||||||
|
Entry entry = newEntry();
|
||||||
|
entry->key = key;
|
||||||
|
entry->value = value;
|
||||||
|
entry->next = hashMap->list[index].next;
|
||||||
|
hashMap->list[index].next = entry;
|
||||||
|
hashMap->size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hashMap->autoAssign && hashMap->size >= hashMap->listSize) {
|
||||||
|
|
||||||
|
// 内存扩充至原来的两倍
|
||||||
|
// *注: 扩充时考虑的是当前存储元素数量与存储空间的大小关系,而不是存储空间是否已经存满,
|
||||||
|
// 例如: 存储空间为10,存入了10个键值对,但是全部冲突了,所以存储空间空着9个,其余的全部挂在一个上面,
|
||||||
|
// 这样检索的时候和遍历查询没有什么区别了,可以简单这样理解,当我存入第11个键值对的时候一定会发生冲突,
|
||||||
|
// 这是由哈希函数本身的特性(取模)决定的,冲突就会导致检索变慢,所以这时候扩充存储空间,对原有键值对进行
|
||||||
|
// 再次散列,会把冲突的数据再次分散开,加快索引定位速度。
|
||||||
|
resetHashMap(hashMap, hashMap->listSize * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let defaultGet(HashMap hashMap, let key) {
|
||||||
|
if (hashMap->exists(hashMap, key)) {
|
||||||
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
|
Entry entry = &hashMap->list[index];
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (hashMap->equal(entry->key, key)) {
|
||||||
|
return entry->value;
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
let defaultRemove(HashMap hashMap, let key) {
|
||||||
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
|
Entry entry = &hashMap->list[index];
|
||||||
|
if (entry->key == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
let entryKey = entry->key;
|
||||||
|
Boolean result = False;
|
||||||
|
if (hashMap->equal(entry->key, key)) {
|
||||||
|
hashMap->size--;
|
||||||
|
if (entry->next != NULL) {
|
||||||
|
Entry temp = entry->next;
|
||||||
|
entry->key = temp->key;
|
||||||
|
entry->value = temp->value;
|
||||||
|
entry->next = temp->next;
|
||||||
|
free(temp);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry->key = NULL;
|
||||||
|
entry->value = NULL;
|
||||||
|
}
|
||||||
|
result = True;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Entry p = entry;
|
||||||
|
entry = entry->next;
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (hashMap->equal(entry->key, key)) {
|
||||||
|
hashMap->size--;
|
||||||
|
p->next = entry->next;
|
||||||
|
free(entry);
|
||||||
|
result = True;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = entry;
|
||||||
|
entry = entry->next;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果空间占用不足一半,则释放多余内存
|
||||||
|
if (result && hashMap->autoAssign && hashMap->size < hashMap->listSize / 2) {
|
||||||
|
resetHashMap(hashMap, hashMap->listSize / 2);
|
||||||
|
}
|
||||||
|
return entryKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean defaultExists(HashMap hashMap, let key) {
|
||||||
|
int index = hashMap->hashCode(hashMap, key);
|
||||||
|
Entry entry = &hashMap->list[index];
|
||||||
|
if (entry->key == NULL) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (entry != NULL) {
|
||||||
|
if (hashMap->equal(entry->key, key)) {
|
||||||
|
return True;
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void defaultClear(HashMap hashMap) {
|
||||||
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
|
// 释放冲突值内存
|
||||||
|
Entry entry = hashMap->list[i].next;
|
||||||
|
while (entry != NULL) {
|
||||||
|
Entry next = entry->next;
|
||||||
|
free(entry);
|
||||||
|
entry = next;
|
||||||
|
}
|
||||||
|
hashMap->list[i].next = NULL;
|
||||||
|
}
|
||||||
|
// 释放存储空间
|
||||||
|
free(hashMap->list);
|
||||||
|
hashMap->list = NULL;
|
||||||
|
hashMap->size = -1;
|
||||||
|
hashMap->listSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap createHashMap(HashCode hashCode, Equal equal) {
|
||||||
|
HashMap hashMap = newHashMap();
|
||||||
|
if (hashMap == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
hashMap->size = 0;
|
||||||
|
hashMap->listSize = 8;
|
||||||
|
hashMap->hashCode = hashCode == NULL ? defaultHashCode : hashCode;
|
||||||
|
hashMap->equal = equal == NULL ? defaultEqual : equal;
|
||||||
|
hashMap->exists = defaultExists;
|
||||||
|
hashMap->get = defaultGet;
|
||||||
|
hashMap->put = defaultPut;
|
||||||
|
hashMap->remove = defaultRemove;
|
||||||
|
hashMap->clear = defaultClear;
|
||||||
|
hashMap->autoAssign = True;
|
||||||
|
|
||||||
|
// 起始分配8个内存空间,溢出时会自动扩充
|
||||||
|
hashMap->list = newEntryList(hashMap->listSize);
|
||||||
|
if (hashMap->list == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Entry p = hashMap->list;
|
||||||
|
for (int i = 0; i < hashMap->listSize; i++) {
|
||||||
|
p[i].key = p[i].value = p[i].next = NULL;
|
||||||
|
}
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMapIterator createHashMapIterator(HashMap hashMap) {
|
||||||
|
HashMapIterator iterator = newHashMapIterator();
|
||||||
|
if (iterator == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
iterator->hashMap = hashMap;
|
||||||
|
iterator->count = 0;
|
||||||
|
iterator->hashCode = -1;
|
||||||
|
iterator->entry = NULL;
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean hasNextHashMapIterator(HashMapIterator iterator) {
|
||||||
|
return iterator->count < iterator->hashMap->size ? True : False;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMapIterator nextHashMapIterator(HashMapIterator iterator) {
|
||||||
|
if (hasNextHashMapIterator(iterator)) {
|
||||||
|
if (iterator->entry != NULL && iterator->entry->next != NULL) {
|
||||||
|
iterator->count++;
|
||||||
|
iterator->entry = iterator->entry->next;
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
while (++iterator->hashCode < iterator->hashMap->listSize) {
|
||||||
|
Entry entry = &iterator->hashMap->list[iterator->hashCode];
|
||||||
|
if (entry->key != NULL) {
|
||||||
|
iterator->count++;
|
||||||
|
iterator->entry = entry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeHashMapIterator(HashMapIterator * iterator) {
|
||||||
|
free(*iterator);
|
||||||
|
*iterator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Put(map, key, value) map->put(map, (void *)key, (void *)value);
|
||||||
|
#define Get(map, key) (char *)map->get(map, (void *)key)
|
||||||
|
#define Remove(map, key) map->remove(map, (void *)key)
|
||||||
|
#define Existe(map, key) map->exists(map, (void *)key)
|
||||||
|
|
||||||
|
void TestHash() {
|
||||||
|
HashMap map = createHashMap(NULL, NULL);
|
||||||
|
Put(map, "000123", "Annie");
|
||||||
|
Put(map, "000245", "Bob");
|
||||||
|
Put(map, "000284", "Daniel");
|
||||||
|
Put(map, "000281", "Luna");
|
||||||
|
Put(map, "000587", "Yao");
|
||||||
|
Put(map, "000985", "Li Ming");
|
||||||
|
Put(map, "000852", "Janne");
|
||||||
|
|
||||||
|
printf("print the key-values in hashmap:\n");
|
||||||
|
HashMapIterator iterator = createHashMapIterator(map);
|
||||||
|
while (hasNextHashMapIterator(iterator)) {
|
||||||
|
iterator = nextHashMapIterator(iterator);
|
||||||
|
printf("{ key: %s, key: %s, hashcode: %d }\n",
|
||||||
|
(char *)iterator->entry->key, (char *)iterator->entry->value, iterator->hashCode);
|
||||||
|
}
|
||||||
|
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
|
||||||
|
printf("000852: %s\n", Get(map, "000852"));
|
||||||
|
printf("remove 000852 %s\n", Remove(map, "000852") ? "true" : "false");
|
||||||
|
printf("key: 000852, exists: %s\n", Existe(map, "000852") ? "true" : "false");
|
||||||
|
|
||||||
|
map->clear(map);
|
||||||
|
freeHashMapIterator(&iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(TestHash, Implement hash_map, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -0,0 +1,129 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file: test_hash.h
|
||||||
|
* @brief: a application of test hash function
|
||||||
|
* @version: 3.0
|
||||||
|
* @author: Yao wenying
|
||||||
|
* @date: 2023/05/26
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __HASHMAP_H__
|
||||||
|
#define __HASHMAP_H__
|
||||||
|
|
||||||
|
#include<stdlib.h>
|
||||||
|
#include<string.h>
|
||||||
|
#include<stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
// 实现数据的基本类型
|
||||||
|
// 字符串类型
|
||||||
|
#define string char *
|
||||||
|
#define newString(str) strcpy((char *)malloc(strlen(str) + 1), str)
|
||||||
|
#define NEW(type) (type *)malloc(sizeof(type))
|
||||||
|
|
||||||
|
// 布尔类型
|
||||||
|
enum _Boolean { True = 1, False = 0 };
|
||||||
|
typedef enum _Boolean Boolean;
|
||||||
|
|
||||||
|
#define let void *
|
||||||
|
|
||||||
|
typedef struct entry {
|
||||||
|
let key; // 键
|
||||||
|
let value; // 值
|
||||||
|
struct entry * next; // 冲突链表
|
||||||
|
}*Entry;
|
||||||
|
|
||||||
|
#define newEntry() NEW(struct entry)
|
||||||
|
#define newEntryList(length) (Entry)malloc(length * sizeof(struct entry))
|
||||||
|
|
||||||
|
// 哈希结构
|
||||||
|
typedef struct hashMap *HashMap;
|
||||||
|
|
||||||
|
#define newHashMap() NEW(struct hashMap)
|
||||||
|
|
||||||
|
// 哈希函数类型
|
||||||
|
typedef int(*HashCode)(HashMap, let key);
|
||||||
|
|
||||||
|
// 判等函数类型
|
||||||
|
typedef Boolean(*Equal)(let key1, let key2);
|
||||||
|
|
||||||
|
// 添加键函数类型
|
||||||
|
typedef void(*Put)(HashMap hashMap, let key, let value);
|
||||||
|
|
||||||
|
// 获取键对应值的函数类型
|
||||||
|
typedef let(*Get)(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 删除键的函数类型
|
||||||
|
typedef let(*Remove)(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 清空Map的函数类型
|
||||||
|
typedef void(*Clear)(HashMap hashMap);
|
||||||
|
|
||||||
|
// 判断键值是否存在的函数类型
|
||||||
|
typedef Boolean(*Exists)(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
typedef struct hashMap {
|
||||||
|
int size; // 当前大小
|
||||||
|
int listSize; // 有效空间大小
|
||||||
|
HashCode hashCode; // 哈希函数
|
||||||
|
Equal equal; // 判等函数
|
||||||
|
Entry list; // 存储区域
|
||||||
|
Put put; // 添加键的函数
|
||||||
|
Get get; // 获取键对应值的函数
|
||||||
|
Remove remove; // 删除键
|
||||||
|
Clear clear; // 清空Map
|
||||||
|
Exists exists; // 判断键是否存在
|
||||||
|
Boolean autoAssign; // 设定是否根据当前数据量动态调整内存大小,默认开启
|
||||||
|
}*HashMap;
|
||||||
|
|
||||||
|
// 迭代器结构
|
||||||
|
typedef struct hashMapIterator {
|
||||||
|
Entry entry; // 迭代器当前指向
|
||||||
|
int count; // 迭代次数
|
||||||
|
int hashCode; // 键值对的哈希值
|
||||||
|
HashMap hashMap;
|
||||||
|
}*HashMapIterator;
|
||||||
|
|
||||||
|
#define newHashMapIterator() NEW(struct hashMapIterator)
|
||||||
|
|
||||||
|
// 默认哈希函数
|
||||||
|
static int defaultHashCode(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 默认判断键值是否相等
|
||||||
|
static Boolean defaultEqual(let key1, let key2);
|
||||||
|
|
||||||
|
// 默认添加键值对
|
||||||
|
static void defaultPut(HashMap hashMap, let key, let value);
|
||||||
|
|
||||||
|
// 默认获取键对应值
|
||||||
|
static let defaultGet(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 默认删除键
|
||||||
|
static let defaultRemove(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 默认判断键是否存在
|
||||||
|
static Boolean defaultExists(HashMap hashMap, let key);
|
||||||
|
|
||||||
|
// 默认清空Map
|
||||||
|
static void defaultClear(HashMap hashMap);
|
||||||
|
|
||||||
|
// 重新构建
|
||||||
|
static void resetHashMap(HashMap hashMap, int listSize);
|
||||||
|
|
||||||
|
// 创建一个哈希结构
|
||||||
|
HashMap createHashMap(HashCode hashCode, Equal equal);
|
||||||
|
|
||||||
|
// 创建哈希结构迭代器
|
||||||
|
HashMapIterator createHashMapIterator(HashMap hashMap);
|
||||||
|
|
||||||
|
// 迭代器是否有下一个
|
||||||
|
Boolean hasNextHashMapIterator(HashMapIterator iterator);
|
||||||
|
|
||||||
|
// 迭代到下一次
|
||||||
|
HashMapIterator nextHashMapIterator(HashMapIterator iterator);
|
||||||
|
|
||||||
|
// 释放迭代器内存
|
||||||
|
void freeHashMapIterator(HashMapIterator * iterator);
|
||||||
|
|
||||||
|
#endif // !__HASHMAP_H__
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define BSP_LED_PIN 134
|
#define BSP_LED_PIN 134
|
||||||
#define NULL_PARAMETER 0
|
#define NULL_PARAMETER 0
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
static uint16_t pin_fd=0;
|
static uint16_t pin_fd=0;
|
||||||
static struct PinStat pin_led;
|
static struct PinStat pin_led;
|
||||||
|
|
||||||
void ledflip(void *parameter)
|
void LedFlip(void *parameter)
|
||||||
{
|
{
|
||||||
pin_led.pin = BSP_LED_PIN;
|
pin_led.pin = BSP_LED_PIN;
|
||||||
pin_led.val = !pin_led.val;
|
pin_led.val = !pin_led.val;
|
||||||
|
@ -68,7 +68,7 @@ void TestHwTimer(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl_cfg.ioctl_driver_type = TIME_TYPE;
|
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)) {
|
if (0 != PrivIoctl(timer_fd, OPE_INT, &ioctl_cfg)) {
|
||||||
printf("timer pin fd error %d\n", pin_fd);
|
printf("timer pin fd error %d\n", pin_fd);
|
||||||
PrivClose(pin_fd);
|
PrivClose(pin_fd);
|
||||||
|
@ -86,9 +86,6 @@ void TestHwTimer(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// int32 timer_handle = KCreateTimer("LED on and off by 1s",&ledflip,&pin_fd,period,TIMER_TRIGGER_PERIODIC);
|
|
||||||
|
|
||||||
// KTimerStartRun(timer_handle);
|
|
||||||
PrivClose(pin_fd);
|
PrivClose(pin_fd);
|
||||||
PrivClose(timer_fd);
|
PrivClose(timer_fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,22 +20,20 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define I2C_SLAVE_ADDRESS 0x0012U
|
#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);
|
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
|
||||||
if (iic_fd < 0)
|
if (iic_fd < 0)
|
||||||
{
|
{
|
||||||
printf("open iic_fd fd error:%d\n", iic_fd);
|
printf("[TestI2C] Open iic_fd fd error: %d\n", iic_fd);
|
||||||
return;
|
return -ERROR;
|
||||||
}
|
}
|
||||||
printf("IIC open successful!\n");
|
printf("[TestI2C] IIC open successful!\n");
|
||||||
|
|
||||||
// init iic
|
|
||||||
uint16 iic_address = I2C_SLAVE_ADDRESS;
|
uint16 iic_address = I2C_SLAVE_ADDRESS;
|
||||||
|
|
||||||
struct PrivIoctlCfg ioctl_cfg;
|
struct PrivIoctlCfg ioctl_cfg;
|
||||||
|
@ -44,28 +42,55 @@ void TestI2C(void)
|
||||||
|
|
||||||
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
|
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);
|
PrivClose(iic_fd);
|
||||||
return;
|
return -ERROR;
|
||||||
}
|
}
|
||||||
printf("IIC configure successful!\n");
|
printf("IIC configure successful!\n");
|
||||||
|
|
||||||
// I2C read and write
|
return iic_fd;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivClose(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
|
|
||||||
#ifdef CONFIG_K210_LCD
|
#ifdef CONFIG_K210_LCD
|
||||||
void LcdDemo(void)
|
void LcdDemo(void)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define GRAPHIC_CTRL_RECT_UPDATE 0x00
|
#define GRAPHIC_CTRL_RECT_UPDATE 0x00
|
||||||
#define LCD_STRING_TYPE 0
|
#define LCD_STRING_TYPE 0
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define NULL_PARAMETER 0
|
#define NULL_PARAMETER 0
|
||||||
#define E220_CFG_LENGTH
|
#define E220_CFG_LENGTH
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
|
|
||||||
#if defined(CONFIG_MUSL_LIBC) && defined(CONFIG_FS_AUTOMOUNTER)
|
#if defined(CONFIG_MUSL_LIBC) && defined(CONFIG_FS_AUTOMOUNTER)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
# 基于k210-emulator实现基数树并测试验证
|
||||||
|
|
||||||
|
## 1. 简介
|
||||||
|
|
||||||
|
基于矽璓模拟器k210-emulator,实现基数树,并编写测试程序在shell终端打印结果。
|
||||||
|
|
||||||
|
## 2. 数据结构设计说明
|
||||||
|
|
||||||
|
基数树节点设计为:
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef struct _node {
|
||||||
|
void* value;
|
||||||
|
struct _node* next[NODE_SIZE];
|
||||||
|
} node;
|
||||||
|
```
|
||||||
|
|
||||||
|
其中,节点在树中的路径即为键,`value` 存储值,`NODE_SIZE` 定义为 128,足以容纳所有 ASCII 值。
|
||||||
|
|
||||||
|
一共实现了 5 个函数,分别为:
|
||||||
|
|
||||||
|
- `CreateNode`:创建一个基数树节点
|
||||||
|
- `InsertNode`:将一对键值对插入基数树
|
||||||
|
- `DeleteNode`:删除指定键的键值对
|
||||||
|
- `FindNode`:查找指定键对应的值
|
||||||
|
- `DestroyTree`:销毁整个基数树
|
||||||
|
|
||||||
|
## 3. 测试程序说明
|
||||||
|
|
||||||
|
测试程序 `TestRadix` 已经注册为 shell 命令,可以调用执行。
|
||||||
|
|
||||||
|
测试程序定义了以下键值对:
|
||||||
|
|
||||||
|
```c
|
||||||
|
char keys[][MAX_WORD_LEN] = {
|
||||||
|
"what",
|
||||||
|
"where",
|
||||||
|
"why",
|
||||||
|
"how",
|
||||||
|
"hello!",
|
||||||
|
"apple",
|
||||||
|
"12345"
|
||||||
|
};
|
||||||
|
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
|
||||||
|
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||||
|
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
|
||||||
|
4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到
|
||||||
|
|
||||||
|
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||||
|
|
||||||
|
1. 在工作区终端中输入命令:`make BOARD=k210-emulator menuconfig`,进入配置页面
|
||||||
|

|
||||||
|
2. 依次进入 `APP_Framework` -> `Applications` -> `test app` 目录,将 `Enable application test function` 选项置为 `Y`
|
||||||
|

|
||||||
|
3. 进入 `Enable application test function` 将 `Config test radix tree` 选项置为 `Y`
|
||||||
|

|
||||||
|
4. 一直选择 `Exit` 退出配置,在最后需要确认的页面选择 `Yes` 保存配置
|
||||||
|

|
||||||
|
5. 执行编译命令:`make BOARD=k210-emulator`,正常情况下应当编译无误
|
||||||
|

|
||||||
|
6. 在 `qemu` 中运行:`qemu-system-riscv64 -nographic -machine sifive_u -bios build/XiZi-k210-emulator.elf`
|
||||||
|

|
||||||
|
7. 在 shell 中运行命令 `TestRadix`,执行结果与预期一致,验证完成。
|
||||||
|

|
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 131 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 238 KiB |
|
@ -0,0 +1,187 @@
|
||||||
|
/**
|
||||||
|
* @file: test_radix_tree.c
|
||||||
|
* @brief: Implement a simple radix tree
|
||||||
|
* @version: 1.0
|
||||||
|
* @date: 2023/5/24
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <transform.h>
|
||||||
|
#include "test_radix_tree.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Create a radix tree node
|
||||||
|
* @return node pointer
|
||||||
|
*/
|
||||||
|
node* CreateNode()
|
||||||
|
{
|
||||||
|
node* n = (node*)malloc(sizeof(node));
|
||||||
|
n->value = NULL;
|
||||||
|
for (int i = 0; i < NODE_SIZE; i++) {
|
||||||
|
n->next[i] = NULL;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Insert a new node to radix tree
|
||||||
|
* @param root - radix tree root
|
||||||
|
* @param key - new node key
|
||||||
|
* @param value - new node value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void InsertNode(node* root, const char* key, void* value)
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
cur->next[b] = CreateNode();
|
||||||
|
}
|
||||||
|
cur = cur->next[b];
|
||||||
|
}
|
||||||
|
cur->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Delete a node from radix tree
|
||||||
|
* @param root - radix tree root
|
||||||
|
* @param key - key which is needed to delete
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void DeleteNode(node* root, const char* key)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_children) {
|
||||||
|
free(*cur);
|
||||||
|
(*cur) = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: find a node by key
|
||||||
|
* @param root - radix tree root
|
||||||
|
* @param key - key which is needed to find
|
||||||
|
* @return value pointer corresponding to key
|
||||||
|
*/
|
||||||
|
void* FindNode(node* root, const char* key)
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
return cur->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: Destroy the radix tree
|
||||||
|
* @param root - radix tree root
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void DestroyTree(node* root)
|
||||||
|
{
|
||||||
|
if (root == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NODE_SIZE; i++) {
|
||||||
|
DestroyTree(root->next[i]);
|
||||||
|
}
|
||||||
|
free(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestRadix()
|
||||||
|
{
|
||||||
|
char keys[][MAX_WORD_LEN] = {
|
||||||
|
"what",
|
||||||
|
"where",
|
||||||
|
"why",
|
||||||
|
"how",
|
||||||
|
"hello!",
|
||||||
|
"apple",
|
||||||
|
"12345"
|
||||||
|
};
|
||||||
|
int values[] = {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");
|
||||||
|
|
||||||
|
int num = sizeof(keys) / sizeof(keys[0]);
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(TestRadix, Implement a simple radix tree, PRIV_SHELL_CMD_MAIN_ATTR);
|
|
@ -0,0 +1,20 @@
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
|
||||||
|
typedef struct _node {
|
||||||
|
void* value;
|
||||||
|
struct _node* next[NODE_SIZE];
|
||||||
|
} node;
|
||||||
|
|
||||||
|
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);
|
|
@ -0,0 +1,69 @@
|
||||||
|
# 基于cortex-m4-emulator实现红黑树并测试验证
|
||||||
|
|
||||||
|
## 1. 简介
|
||||||
|
红黑树是一种自平衡的二叉查找树,具有良好的插入、删除和查找性能,本次提交结果为红黑树数据结构的简单实现。test_rbtree.h中定义了红黑树的数据结构和声明插入、删除、查找相关操作函数;test_rbtree.c中为操作函数的定义,并提供了测试函数TestRBTree用于验证红黑树的正确性。
|
||||||
|
|
||||||
|
|
||||||
|
## 2. 数据结构设计说明
|
||||||
|
|
||||||
|
**RBNodeType 结构体**
|
||||||
|
用来存储一个红黑树结点的相关信息
|
||||||
|
- key:节点的键值
|
||||||
|
- left_child:指向左子节点的指针
|
||||||
|
- right_child:指向右子节点的指针
|
||||||
|
- parent:指向父节点的指针
|
||||||
|
- is_red:表示节点的颜色,true表示红色,false表示黑色
|
||||||
|
|
||||||
|
**RBTreeType 结构体**
|
||||||
|
用来存储一个红黑树的相关信息
|
||||||
|
- root:指向红黑树的根节点的指针
|
||||||
|
- leaf:红黑树的叶节点,由于叶节点并不需要存储数据,故每棵树只分配一个叶节点
|
||||||
|
|
||||||
|
|
||||||
|
**RBTreeTraversal 函数**
|
||||||
|
该函数用于遍历红黑树并打印节点的键值。采用中序遍历的方式,递归地遍历左子树、当前节点和右子树。
|
||||||
|
|
||||||
|
**RBTreeLeftRotate 函数**
|
||||||
|
该函数实现红黑树的左旋转操作。接受一个当前节点指针作为参数,并按照左旋转的规则调整节点和子树的位置。
|
||||||
|
|
||||||
|
**RBTreeRightRotate 函数**
|
||||||
|
该函数实现红黑树的右旋转操作。接受一个当前节点指针作为参数,并按照右旋转的规则调整节点和子树的位置。
|
||||||
|
|
||||||
|
**InsertFixup 函数**
|
||||||
|
该函数用于插入节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。
|
||||||
|
|
||||||
|
**RBTreeInsert 函数**
|
||||||
|
该函数用于向红黑树中插入一个新节点。接受一个新节点指针作为参数,并根据新节点的键值插入到适当的位置,然后调用 InsertFixup 进行修复。
|
||||||
|
|
||||||
|
**DeleteFixup 函数**
|
||||||
|
该函数用于删除节点后修复红黑树的平衡性。接受一个当前节点指针作为参数,并根据红黑树的性质进行旋转和着色操作,以恢复平衡。
|
||||||
|
|
||||||
|
**RBTreeDelete 函数**
|
||||||
|
该函数用于从红黑树中删除指定节点。接受一个目标节点指针作为参数,并根据不同的情况进行节点的替换和删除操作,然后调用 DeleteFixup 进行修复。
|
||||||
|
|
||||||
|
**FindSuccessor 函数**
|
||||||
|
该函数用于查找给定节点的后继节点。接受一个当前节点指针作为参数,并在红黑树中找到当前节点的后继节点。
|
||||||
|
|
||||||
|
**RBTreeSearch 函数**
|
||||||
|
该函数用于在红黑树中查找指定键值的节点。接受一个键值作为参数,并在红黑树中进行查找,返回找到的节点指针。
|
||||||
|
|
||||||
|
## 3. 测试程序说明
|
||||||
|
TestRBTree用于验证红黑树的功能和正确性,下面是该程序的使用步骤和说明:
|
||||||
|
- 函数中定义一个默认关键字数组,其中包含了20个整数关键字,运行时自动遍历数组构建红黑树,构建完成后中序遍历输出结果,可以根据输出结果验证红黑树的节点顺序以及颜色是否符合预期。
|
||||||
|
- 对关键字数组中的每个关键字,在红黑树中进行搜索,并输出找到节点的父节点、左子节点和右子节点的关键字,随后删除该节点。
|
||||||
|
- 在每次删除操作后,程序会询问是否显示当前的红黑树。如果输入 "Y" 或 "y",将再次进行中序遍历,并输出当前红黑树中的结点,可以根据输出结果查看结点是否符合预期。当树空时结束程序。
|
||||||
|
|
||||||
|
|
||||||
|
## 4. 运行结果(##需结合运行测试截图按步骤说明##)
|
||||||
|
|
||||||
|
根据默认关键字数组构建红黑树
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
根据键值查找结点,输出相关信息并删除,可以输入'Y'或'y'展示删除后的红黑树
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
到达空树,退出程序
|
||||||
|
|
||||||
|

|
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 125 KiB |
|
@ -0,0 +1,341 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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_rbtree.c
|
||||||
|
* @brief: a application of red-black tree function
|
||||||
|
* @version: 1.0
|
||||||
|
* @author: AIIT XUOS Lab
|
||||||
|
* @date: 2023/6/23
|
||||||
|
*/
|
||||||
|
#include<string.h>
|
||||||
|
#include <transform.h>
|
||||||
|
#include"test_rbtree.h"
|
||||||
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
|
void RBTreeTraversal(RBTreeType *tree, RBNodeType *node)
|
||||||
|
{
|
||||||
|
if (node != tree->leaf) {
|
||||||
|
RBTreeTraversal(tree, node->left_child);
|
||||||
|
printf("key:%d, color:%s\n", node->key, (node->is_red ? "Red" : "Black"));
|
||||||
|
RBTreeTraversal(tree, node->right_child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RBNodeType* RBTreeSearch(RBTreeType *tree, int key)
|
||||||
|
{
|
||||||
|
RBNodeType* current_node = tree->root;
|
||||||
|
while (current_node != tree->leaf){
|
||||||
|
if (key < current_node->key)
|
||||||
|
current_node = current_node->left_child;
|
||||||
|
else if (key > current_node->key)
|
||||||
|
current_node = current_node->right_child;
|
||||||
|
else
|
||||||
|
return current_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree->leaf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node)
|
||||||
|
{
|
||||||
|
RBNodeType* child_node = current_node->right_child;
|
||||||
|
|
||||||
|
current_node->right_child = child_node->left_child;
|
||||||
|
if (child_node->left_child != tree->leaf)
|
||||||
|
child_node->left_child->parent = current_node;
|
||||||
|
|
||||||
|
child_node->parent = current_node->parent;
|
||||||
|
if (current_node->parent == tree->leaf)
|
||||||
|
tree->root = child_node;
|
||||||
|
else if (current_node == current_node->parent->left_child)
|
||||||
|
current_node->parent->left_child = child_node;
|
||||||
|
else
|
||||||
|
current_node->parent->right_child = child_node;
|
||||||
|
|
||||||
|
child_node->left_child = current_node;
|
||||||
|
current_node->parent = child_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node)
|
||||||
|
{
|
||||||
|
RBNodeType* child_node = current_node->left_child;
|
||||||
|
|
||||||
|
current_node->left_child = child_node->right_child;
|
||||||
|
if (child_node->right_child != tree->leaf)
|
||||||
|
child_node->right_child->parent = current_node;
|
||||||
|
|
||||||
|
child_node->parent = current_node->parent;
|
||||||
|
if (current_node->parent == tree->leaf)
|
||||||
|
tree->root = child_node;
|
||||||
|
else if (current_node == current_node->parent->right_child)
|
||||||
|
current_node->parent->right_child = child_node;
|
||||||
|
else
|
||||||
|
current_node->parent->left_child = child_node;
|
||||||
|
|
||||||
|
child_node->right_child = current_node;
|
||||||
|
current_node->parent = child_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertFixup(RBTreeType *tree, RBNodeType* current_node)
|
||||||
|
{
|
||||||
|
while (current_node->parent->is_red){
|
||||||
|
/* The parent of current_node is the left subtree of the grandfather */
|
||||||
|
if (current_node->parent == current_node->parent->parent->left_child){
|
||||||
|
RBNodeType * uncle_node = current_node->parent->parent->right_child;
|
||||||
|
if (uncle_node->is_red){ /* case1:red uncle and red parent, change color */
|
||||||
|
uncle_node->is_red = false;
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
current_node->parent->parent->is_red = true;
|
||||||
|
|
||||||
|
current_node = current_node->parent->parent;
|
||||||
|
}else{ /* case2:black uncle and red parent, need rotation */
|
||||||
|
if (current_node->parent->right_child == current_node){
|
||||||
|
current_node = current_node->parent;
|
||||||
|
RBTreeLeftRotate(tree, current_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
current_node->parent->parent->is_red = true;
|
||||||
|
RBTreeRightRotate(tree, current_node->parent->parent);
|
||||||
|
}
|
||||||
|
/* The parent of current_node is the right subtree of the grandfather, same with left subtree */
|
||||||
|
}else{
|
||||||
|
RBNodeType * uncle_node = current_node->parent->parent->left_child;
|
||||||
|
if (uncle_node->is_red){
|
||||||
|
uncle_node->is_red = false;
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
current_node->parent->parent->is_red = true;
|
||||||
|
|
||||||
|
current_node = current_node->parent->parent;
|
||||||
|
}else{
|
||||||
|
if (current_node->parent->left_child == current_node){
|
||||||
|
current_node = current_node->parent;
|
||||||
|
RBTreeRightRotate(tree, current_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
current_node->parent->parent->is_red = true;
|
||||||
|
RBTreeLeftRotate(tree, current_node->parent->parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree->root->is_red = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node)
|
||||||
|
{
|
||||||
|
RBNodeType* previous_node = tree->root;
|
||||||
|
RBNodeType* current_node = tree->root;
|
||||||
|
|
||||||
|
while (current_node != tree->leaf){
|
||||||
|
previous_node = current_node;
|
||||||
|
if (new_node->key > current_node->key)
|
||||||
|
current_node = current_node->right_child;
|
||||||
|
else if (new_node->key < current_node->key)
|
||||||
|
current_node = current_node->left_child;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous_node == tree->leaf){
|
||||||
|
tree->root = new_node;
|
||||||
|
tree->root->parent = tree->leaf;
|
||||||
|
}else{
|
||||||
|
new_node->parent = previous_node;
|
||||||
|
|
||||||
|
if (previous_node->key > new_node->key)
|
||||||
|
previous_node->left_child = new_node;
|
||||||
|
else
|
||||||
|
previous_node->right_child = new_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
InsertFixup(tree, new_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node)
|
||||||
|
{
|
||||||
|
RBNodeType* parent_node = current_node->parent;
|
||||||
|
if (current_node->right_child != tree->leaf){
|
||||||
|
current_node = current_node->right_child;
|
||||||
|
while (current_node->left_child != tree->leaf)
|
||||||
|
current_node = current_node->left_child;
|
||||||
|
return current_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((parent_node != tree->leaf) && (current_node == parent_node->right_child)){
|
||||||
|
current_node = parent_node;
|
||||||
|
parent_node = parent_node->parent;
|
||||||
|
}
|
||||||
|
return parent_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeleteFixup(RBTreeType *tree, RBNodeType* current_node)
|
||||||
|
{
|
||||||
|
while ((current_node != tree->root) && (current_node->is_red == false)){
|
||||||
|
if (current_node == current_node->parent->left_child){
|
||||||
|
|
||||||
|
RBNodeType* brother_node = current_node->parent->right_child;
|
||||||
|
if (brother_node->is_red){
|
||||||
|
brother_node->is_red = false;
|
||||||
|
current_node->parent->is_red = true;
|
||||||
|
RBTreeLeftRotate(tree, current_node->parent);
|
||||||
|
brother_node = current_node->parent->right_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){
|
||||||
|
brother_node->is_red = true;
|
||||||
|
current_node = current_node->parent;
|
||||||
|
}else{
|
||||||
|
if (brother_node->right_child->is_red == false){
|
||||||
|
brother_node->left_child->is_red = false;
|
||||||
|
brother_node->is_red = true;
|
||||||
|
RBTreeRightRotate(tree, brother_node);
|
||||||
|
brother_node = current_node->parent->right_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
brother_node->is_red = current_node->parent->is_red;
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
brother_node->right_child->is_red = false;
|
||||||
|
RBTreeLeftRotate(tree, current_node->parent);
|
||||||
|
current_node = tree->root;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
RBNodeType* brother_node = current_node->parent->left_child;
|
||||||
|
if (brother_node->is_red){
|
||||||
|
brother_node->is_red = false;
|
||||||
|
current_node->parent->is_red = true;
|
||||||
|
RBTreeRightRotate(tree, current_node->parent);
|
||||||
|
brother_node = current_node->parent->left_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((brother_node->left_child->is_red == false) && (brother_node->right_child->is_red == false)){
|
||||||
|
brother_node->is_red = true;
|
||||||
|
current_node = current_node->parent;
|
||||||
|
}else{
|
||||||
|
if (brother_node->left_child->is_red == false){
|
||||||
|
brother_node->right_child->is_red = false;
|
||||||
|
brother_node->is_red = true;
|
||||||
|
RBTreeLeftRotate(tree, brother_node);
|
||||||
|
brother_node = current_node->parent->left_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
brother_node->is_red = current_node->parent->is_red;
|
||||||
|
current_node->parent->is_red = false;
|
||||||
|
brother_node->left_child->is_red = false;
|
||||||
|
RBTreeRightRotate(tree, current_node->parent);
|
||||||
|
current_node = tree->root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_node->is_red = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node)
|
||||||
|
{
|
||||||
|
RBNodeType* delete_node = tree->leaf;
|
||||||
|
RBNodeType* replace_node = tree->leaf;
|
||||||
|
|
||||||
|
if ((target_node->left_child == tree->leaf) || (target_node->right_child == tree->leaf))
|
||||||
|
delete_node = target_node;
|
||||||
|
else
|
||||||
|
delete_node = FindSuccessor(tree, target_node);
|
||||||
|
|
||||||
|
if (delete_node->left_child != tree->leaf) /* successor still has subtree */
|
||||||
|
replace_node = delete_node->left_child;
|
||||||
|
else if (delete_node->right_child != tree->leaf)
|
||||||
|
replace_node = delete_node->right_child;
|
||||||
|
|
||||||
|
replace_node->parent = delete_node->parent;
|
||||||
|
|
||||||
|
if (delete_node->parent == tree->leaf) /* delete a root node */
|
||||||
|
tree->root = replace_node;
|
||||||
|
else if (delete_node == delete_node->parent->left_child)
|
||||||
|
delete_node->parent->left_child = replace_node;
|
||||||
|
else
|
||||||
|
delete_node->parent->right_child = replace_node;
|
||||||
|
|
||||||
|
if (delete_node != target_node)
|
||||||
|
target_node->key = delete_node->key;
|
||||||
|
|
||||||
|
if (delete_node->is_red == false)
|
||||||
|
DeleteFixup(tree, replace_node);
|
||||||
|
|
||||||
|
free(delete_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TestRBTree(void)
|
||||||
|
{
|
||||||
|
int default_key[] = { 16, 25, 23, 5, 2, 6, 17, 37, 38, 98, 20, 19, 47, 49, 12, 21, 9, 18, 14, 15 };
|
||||||
|
int array_size = sizeof(default_key) / sizeof(default_key[0]);
|
||||||
|
|
||||||
|
printf("Test Red Black Tree\n");
|
||||||
|
printf("default_key array: ");
|
||||||
|
for (int i = 0; i < array_size; i++)
|
||||||
|
printf("%d ", default_key[i]);
|
||||||
|
printf("\n%d elements\n", array_size);
|
||||||
|
|
||||||
|
RBTreeType *tree = (RBTreeType *)malloc(sizeof(RBTreeType));
|
||||||
|
if (tree == NULL) {
|
||||||
|
printf("malloc failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree->leaf = (RBNodeType*)malloc(sizeof(RBNodeType));
|
||||||
|
tree->leaf->left_child = NULL;
|
||||||
|
tree->leaf->right_child = NULL;
|
||||||
|
tree->leaf->parent = NULL;
|
||||||
|
tree->leaf->is_red = false;
|
||||||
|
tree->leaf->key = -1;
|
||||||
|
tree->root = tree->leaf;
|
||||||
|
|
||||||
|
RBNodeType *node = tree->leaf;
|
||||||
|
|
||||||
|
for (int i = 0; i < array_size; i++) {
|
||||||
|
node = (RBNodeType*)malloc(sizeof(RBNodeType));
|
||||||
|
node->left_child = tree->leaf;
|
||||||
|
node->right_child = tree->leaf;
|
||||||
|
node->parent = NULL;
|
||||||
|
node->is_red = true;
|
||||||
|
node->key = default_key[i];
|
||||||
|
printf("insert key[%d]=%d\n",i,default_key[i]);
|
||||||
|
RBTreeInsert(tree, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("------------------Inorder Traversal------------------\n");
|
||||||
|
RBTreeTraversal(tree, tree->root);
|
||||||
|
|
||||||
|
for (int i = 0; i < array_size; i++) {
|
||||||
|
printf("search key = %d\n", default_key[i]);
|
||||||
|
node = RBTreeSearch(tree, default_key[i]);
|
||||||
|
printf("search succeeded, parent node: %d, left-child: %d, right-child: %d\n", node->parent->key, node->left_child->key, node->right_child->key);
|
||||||
|
|
||||||
|
printf("delete key = %d\n", node->key);
|
||||||
|
RBTreeDelete(tree, node);
|
||||||
|
|
||||||
|
printf("Show current tree?Y/N \n");
|
||||||
|
char ch;
|
||||||
|
scanf("%c", &ch);
|
||||||
|
if (ch == 'Y' || ch == 'y') {
|
||||||
|
printf("------------------Inorder Traversal Tree After Deletion------------------\n");
|
||||||
|
if (tree->root != tree->leaf)
|
||||||
|
RBTreeTraversal(tree, tree->root);
|
||||||
|
else
|
||||||
|
printf("the tree is empty.\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(TestRBTree, a red-black tree test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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_rbtree.h
|
||||||
|
* @brief: a head file of red-black tree structure
|
||||||
|
* @version: 1.0
|
||||||
|
* @author: AIIT XUOS Lab
|
||||||
|
* @date: 2023/6/23
|
||||||
|
*/
|
||||||
|
#ifndef REDBLACKTREE_H_
|
||||||
|
#define REDBLACKTREE_H_
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
typedef struct RedBlackNode
|
||||||
|
{
|
||||||
|
int key;
|
||||||
|
struct RedBlackNode *left_child;
|
||||||
|
struct RedBlackNode *right_child;
|
||||||
|
struct RedBlackNode *parent;
|
||||||
|
bool is_red;
|
||||||
|
} RBNodeType;
|
||||||
|
|
||||||
|
typedef struct RedBlackTree
|
||||||
|
{
|
||||||
|
RBNodeType *root;
|
||||||
|
RBNodeType *leaf;
|
||||||
|
} RBTreeType;
|
||||||
|
|
||||||
|
void TestRBTree(void);
|
||||||
|
|
||||||
|
void RBTreeTraversal(RBTreeType *tree, RBNodeType *node);
|
||||||
|
|
||||||
|
void RBTreeLeftRotate(RBTreeType *tree, RBNodeType *current_node);
|
||||||
|
|
||||||
|
void RBTreeRightRotate(RBTreeType *tree, RBNodeType* current_node);
|
||||||
|
|
||||||
|
void InsertFixup(RBTreeType *tree, RBNodeType* current_node);
|
||||||
|
|
||||||
|
void RBTreeInsert(RBTreeType *tree, RBNodeType* new_node);
|
||||||
|
|
||||||
|
void DeleteFixup(RBTreeType *tree, RBNodeType* current_node);
|
||||||
|
|
||||||
|
void RBTreeDelete(RBTreeType *tree, RBNodeType* target_node);
|
||||||
|
|
||||||
|
RBNodeType* FindSuccessor(RBTreeType *tree, RBNodeType* current_node);
|
||||||
|
|
||||||
|
RBNodeType* RBTreeSearch(RBTreeType *tree, int key);
|
||||||
|
|
||||||
|
#endif
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
#define BSP_485_DIR_PIN 24
|
#define BSP_485_DIR_PIN 24
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestRTC(int argc,char *argv[])
|
void TestRTC(int argc,char *argv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 <argparse.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <transform.h>
|
||||||
|
|
||||||
|
#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));
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
|
|
||||||
#ifdef CONFIG_BSP_USING_TOUCH
|
#ifdef CONFIG_BSP_USING_TOUCH
|
||||||
void TestTouch(void)
|
void TestTouch(void)
|
||||||
|
@ -48,7 +48,7 @@ void TestTouch(void)
|
||||||
#define LCD_DOT_TYPE 1
|
#define LCD_DOT_TYPE 1
|
||||||
#define LCD_SIZE 320
|
#define LCD_SIZE 320
|
||||||
|
|
||||||
#elif defined ADD_XIZI_FETURES
|
#elif defined ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestTouch(void)
|
void TestTouch(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <transform.h>
|
||||||
|
|
||||||
|
#include <argparse.h>
|
||||||
|
#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
|
|
@ -20,7 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestWDT(int argc, char *agrv[])
|
void TestWDT(int argc, char *agrv[])
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
|
|
||||||
ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y)
|
ifeq ($(CONFIG_CONNECTION_ADAPTER_4G),y)
|
||||||
SRC_DIR += 4g_app
|
SRC_DIR += 4g_app
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* 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 modbus_rtu_app.c
|
||||||
|
* @brief support get data from and send data to Modbus rtu server
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2022.12.12
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <transform.h>
|
||||||
|
#include <adapter.h>
|
||||||
|
|
||||||
|
#define ADAPTER_RTU_DATA_LENGTH 112
|
||||||
|
#define ADAPTER_RTU_TRANSFER_DATA_LENGTH ADAPTER_RTU_DATA_LENGTH + 16
|
||||||
|
|
||||||
|
uint8_t client_join_data[ADAPTER_RTU_TRANSFER_DATA_LENGTH];
|
||||||
|
|
||||||
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
|
#include "mb.h"
|
||||||
|
#include "mbport.h"
|
||||||
|
|
||||||
|
/* ----------------------- Defines ------------------------------------------*/
|
||||||
|
#define REG_INPUT_START 1000
|
||||||
|
#define REG_INPUT_NREGS 4
|
||||||
|
|
||||||
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
|
static USHORT usRegInputStart = REG_INPUT_START;
|
||||||
|
static USHORT usRegInputBuf[REG_INPUT_NREGS];
|
||||||
|
|
||||||
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
int iRegIndex;
|
||||||
|
|
||||||
|
if( ( usAddress >= REG_INPUT_START )
|
||||||
|
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
|
||||||
|
{
|
||||||
|
iRegIndex = ( int )( usAddress - usRegInputStart );
|
||||||
|
while( usNRegs > 0 )
|
||||||
|
{
|
||||||
|
*pucRegBuffer++ =
|
||||||
|
( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
|
||||||
|
*pucRegBuffer++ =
|
||||||
|
( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
|
||||||
|
iRegIndex++;
|
||||||
|
usNRegs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eStatus = MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
|
||||||
|
eMBRegisterMode eMode )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
|
||||||
|
eMBRegisterMode eMode )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************Modbus RTU TEST*********************/
|
||||||
|
int AdapterModbusRtuTest(void)
|
||||||
|
{
|
||||||
|
const char *send_msg = "Adapter_Modbus_Rtu Test";
|
||||||
|
char recv_msg[256] = {0};
|
||||||
|
int baud_rate = BAUD_RATE_115200;
|
||||||
|
|
||||||
|
struct Adapter* adapter = AdapterDeviceFindByName(ADAPTER_MODBUS_RTU_NAME);
|
||||||
|
|
||||||
|
struct AdapterData priv_rtu_net;
|
||||||
|
priv_rtu_net.len = ADAPTER_RTU_TRANSFER_DATA_LENGTH;
|
||||||
|
priv_rtu_net.buffer = client_join_data;
|
||||||
|
|
||||||
|
|
||||||
|
AdapterDeviceOpen(adapter);
|
||||||
|
AdapterDeviceControl(adapter, OPE_INT, &baud_rate);
|
||||||
|
|
||||||
|
AdapterDeviceJoin(adapter,(uint8_t *)&priv_rtu_net);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
eMBErrorCode eStatus;
|
||||||
|
|
||||||
|
eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN );
|
||||||
|
|
||||||
|
/* Enable the Modbus Protocol Stack. */
|
||||||
|
eStatus = eMBEnable( );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
( void )eMBPoll( );//判断事件的发生,并执行对应的回调函数
|
||||||
|
|
||||||
|
/* Here we simply count the number of poll cycles. */
|
||||||
|
usRegInputBuf[0]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// while (1) {
|
||||||
|
// AdapterDeviceSend(adapter, send_msg, strlen(send_msg));
|
||||||
|
// AdapterDeviceRecv(adapter, recv_msg, 256);
|
||||||
|
// printf("4G recv msg %s\n", recv_msg);
|
||||||
|
// memset(recv_msg, 0, 256);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(AdapterModbusRtuTest, a Modbus Rtu adpter sample, PRIV_SHELL_CMD_FUNC_ATTR);
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := lwip_tcp_socket_demo.c lwip_udp_socket_demo.c
|
SRC_FILES := lwip_tcp_socket_demo.c lwip_udp_socket_demo.c
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += lwip_tcp_socket_demo.c lwip_udp_socket_demo.c
|
CSRCS += lwip_tcp_socket_demo.c lwip_udp_socket_demo.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
|
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
#include <sys_arch.h>
|
#include <sys_arch.h>
|
||||||
#include <lwip/sockets.h>
|
#include <lwip/sockets.h>
|
||||||
#include "lwip/sys.h"
|
#include "lwip/sys.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -45,7 +45,7 @@ static char tcp_demo_ipaddr[] = {192, 168, 131, 77};
|
||||||
static char tcp_demo_netmask[] = {255, 255, 254, 0};
|
static char tcp_demo_netmask[] = {255, 255, 254, 0};
|
||||||
static char tcp_demo_gwaddr[] = {192, 168, 131, 1};
|
static char tcp_demo_gwaddr[] = {192, 168, 131, 1};
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
#define lw_print printf
|
#define lw_print printf
|
||||||
#define lw_notice printf
|
#define lw_notice printf
|
||||||
#define lw_error printf
|
#define lw_error printf
|
||||||
|
@ -151,7 +151,7 @@ void TcpSocketRecvTest(int argc, char *argv[])
|
||||||
TcpSocketConfigParam(argv[1]);
|
TcpSocketConfigParam(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
@ -159,7 +159,7 @@ void TcpSocketRecvTest(int argc, char *argv[])
|
||||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||||
|
@ -222,14 +222,14 @@ void TcpSocketSendTest(int argc, char *argv[])
|
||||||
TcpSocketConfigParam(argv[1]);
|
TcpSocketConfigParam(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO;
|
attr.schedparam.sched_priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||||
|
|
|
@ -19,12 +19,12 @@
|
||||||
*/
|
*/
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
#include <sys_arch.h>
|
#include <sys_arch.h>
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -133,14 +133,14 @@ void UdpSocketRecvTest(int argc, char *argv[])
|
||||||
UdpSocketConfigParam(argv[1]);
|
UdpSocketConfigParam(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||||
attr.priority = LWIP_UDP_DEMO_TASK_PRIO;
|
attr.priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||||
|
@ -199,14 +199,14 @@ void UdpSocketSendTest(int argc, char *argv[])
|
||||||
UdpSocketConfigParam(argv[1]);
|
UdpSocketConfigParam(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
lwip_config_tcp(0, udp_demo_ipaddr, udp_demo_netmask, udp_demo_gwaddr);
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
attr.schedparam.sched_priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||||
attr.priority = LWIP_UDP_DEMO_TASK_PRIO;
|
attr.priority = LWIP_UDP_DEMO_TASK_PRIO;
|
||||||
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
attr.stacksize = LWIP_UDP_DEMO_TASK_STACK_SIZE;
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance
|
SRC_DIR := advantech beckhoff br delta mitsubishi omron schneider siemens ge xinje inovance keyence
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c
|
SRC_FILES := inovance_am401_cpu1608tn_ethernet.c inovance_am401_cpu1608tn_uart.c
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* 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 inovance_am401_cpu1608tn_ethernet.c
|
||||||
|
* @brief PLC inovance am401 app
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023.5.15
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <control.h>
|
||||||
|
|
||||||
|
extern int Adapter4GActive(void);
|
||||||
|
|
||||||
|
void ControlInovanceam401UartTest(void)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
int read_data_length = 0;
|
||||||
|
uint8_t read_data[128] = {0};
|
||||||
|
|
||||||
|
#ifdef CONNECTION_ADAPTER_4G
|
||||||
|
Adapter4GActive();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ControlProtocolType modbus_rtu_protocol = ControlProtocolFind();
|
||||||
|
if (NULL == modbus_rtu_protocol) {
|
||||||
|
printf("%s get modbus rtu protocol %p failed\n", __func__, modbus_rtu_protocol);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s get modbus rtu protocol %p successfull\n", __func__, modbus_rtu_protocol);
|
||||||
|
|
||||||
|
if (CONTROL_REGISTERED == modbus_rtu_protocol->protocol_status) {
|
||||||
|
ControlProtocolOpen(modbus_rtu_protocol);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
read_data_length = ControlProtocolRead(modbus_rtu_protocol, read_data, sizeof(read_data));
|
||||||
|
printf("%s read [%d] modbus rtu data %d using receipe file\n", __func__, i, read_data_length);
|
||||||
|
if (read_data_length) {
|
||||||
|
for (j = 0; j < read_data_length; j ++) {
|
||||||
|
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
memset(read_data, 0, sizeof(read_data));
|
||||||
|
PrivTaskDelay(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
//ControlProtocolClose(modbus_rtu_protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(ControlInovanceam401UartTest, inovance am401 uart Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
{
|
||||||
|
"device_id": 1,
|
||||||
|
"device_name": "INOVANCE_am401_RTU",
|
||||||
|
"communication_type": 1,
|
||||||
|
"serial_config": {
|
||||||
|
"station": 1,
|
||||||
|
"baud_rate": 9600,
|
||||||
|
"data_bits": 8,
|
||||||
|
"stop_bits": 1,
|
||||||
|
"check_mode":3
|
||||||
|
},
|
||||||
|
"protocol_type": 3,
|
||||||
|
"read_period": 2000,
|
||||||
|
"read_item_list": [
|
||||||
|
{
|
||||||
|
"value_name": "q00",
|
||||||
|
"value_type": 1,
|
||||||
|
"function_code": 1,
|
||||||
|
"start_address": 0,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "q01",
|
||||||
|
"value_type": 1,
|
||||||
|
"function_code": 1,
|
||||||
|
"start_address":1,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "q10",
|
||||||
|
"value_type": 1,
|
||||||
|
"function_code": 1,
|
||||||
|
"start_address": 8,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "mw100",
|
||||||
|
"value_type": 3,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 100,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "mw101",
|
||||||
|
"value_type": 3,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 101,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "md200",
|
||||||
|
"value_type": 4,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 400,
|
||||||
|
"quantity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "md201",
|
||||||
|
"value_type": 4,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 402,
|
||||||
|
"quantity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "md300",
|
||||||
|
"value_type": 9,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 600,
|
||||||
|
"quantity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "md301",
|
||||||
|
"value_type": 9,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 602,
|
||||||
|
"quantity": 2
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
SRC_FILES := ethernetif.c
|
SRC_FILES := kv_8000.c
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -0,0 +1,66 @@
|
||||||
|
# keyence通信测试
|
||||||
|
|
||||||
|
[TOC]
|
||||||
|
|
||||||
|
## 通信接线及参数设置
|
||||||
|
|
||||||
|
* 网口
|
||||||
|
|
||||||
|
*Mosbus TCP协议,IP:192.168.250.40,Port:502
|
||||||
|
|
||||||
|
## 存储区
|
||||||
|
|
||||||
|
- 存储区ZF区。
|
||||||
|
|
||||||
|
## JSON配方设计
|
||||||
|
|
||||||
|
* 共测试INT16共1种类型数据,以下为JSON文件解释。
|
||||||
|
|
||||||
|
- ```json
|
||||||
|
{
|
||||||
|
"device_id": 1, //设备ID默认是1,此参数无效
|
||||||
|
"device_name": "KV8000", //设备名称,自定义
|
||||||
|
"communication_type": 0, //通讯协议类型 0是以太网,1是串口
|
||||||
|
"socket_config": { //以太网配置
|
||||||
|
"plc_ip": "192.168.250.40", //PLC的IP地址
|
||||||
|
"local_ip": "192.168.250.233", //矽达通IP地址设定
|
||||||
|
"gateway": "192.168.250.1", //矽达通的网关地址设定
|
||||||
|
"netmask": "255.255.255.0", //矽达通子网掩码设定
|
||||||
|
"port":502 //端口号设定
|
||||||
|
},
|
||||||
|
"protocol_type": 3, //通讯协议,3代表modbus-tcp协议
|
||||||
|
"read_period": 100, //交互周期ms
|
||||||
|
"read_item_list": [
|
||||||
|
{
|
||||||
|
"value_name": "ZF0", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3是读
|
||||||
|
"start_address": 0, //起始地址
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "ZF2", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3/6是读
|
||||||
|
"start_address": 2, //起始地址偏移1位
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 通信测试
|
||||||
|
|
||||||
|
(1) 新增1个通信demo,命名为keyence_KV8000.c;
|
||||||
|
|
||||||
|
(2) 复制样例代码程序到keyence_KV8000.c文件中;
|
||||||
|
|
||||||
|
(3) void **ControlKV8000Test**(void) 更改函数名;
|
||||||
|
|
||||||
|
(4) PRIV_SHELL_CMD_FUNCTION(**ControKV8000Test**, keyence plc KV8000 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||||
|
|
||||||
|
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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 kv_8000.c
|
||||||
|
* @brief PLC KEYENCE KV-8000 app
|
||||||
|
* @version 3.0
|
||||||
|
* @author AIIT XUOS Lab
|
||||||
|
* @date 2023.4.12
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <control.h>
|
||||||
|
void ControlKV8000Test(void)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
int read_data_length = 0;
|
||||||
|
uint8_t read_data[128] = {0};
|
||||||
|
ControlProtocolType modbus_tcp_protocol = ControlProtocolFind();
|
||||||
|
if (NULL == modbus_tcp_protocol) {
|
||||||
|
printf("%s get modbus tcp protocol %p failed\n", __func__, modbus_tcp_protocol);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("%s get modbus tcp protocol %p successfull\n", __func__, modbus_tcp_protocol);
|
||||||
|
|
||||||
|
if (CONTROL_REGISTERED == modbus_tcp_protocol->protocol_status) {
|
||||||
|
ControlProtocolOpen(modbus_tcp_protocol);
|
||||||
|
for (;;) {
|
||||||
|
read_data_length = ControlProtocolRead(modbus_tcp_protocol, read_data, sizeof(read_data));
|
||||||
|
printf("%s read [%d] modbus tcp data %d using receipe file\n", __func__, i, read_data_length);
|
||||||
|
if (read_data_length) {
|
||||||
|
for (j = 0; j < read_data_length; j ++) {
|
||||||
|
printf("j %d data 0x%x\n", j, read_data[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
memset(read_data, 0, sizeof(read_data));
|
||||||
|
PrivTaskDelay(10000);
|
||||||
|
}
|
||||||
|
//ControlProtocolClose(modbus_tcp_protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(ControlKV8000Test, KEYENCE Plc KV_8000 Demo, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"device_id": 1,
|
||||||
|
"device_name": "GJ2",
|
||||||
|
"communication_type": 0,
|
||||||
|
"socket_config": {
|
||||||
|
"plc_ip": "192.168.250.40",
|
||||||
|
"local_ip": "192.168.250.233",
|
||||||
|
"gateway": "192.168.250.1",
|
||||||
|
"netmask": "255.255.255.0",
|
||||||
|
"port": 502
|
||||||
|
},
|
||||||
|
"protocol_type": 2,
|
||||||
|
"read_period": 100,
|
||||||
|
"read_item_list": [
|
||||||
|
{
|
||||||
|
"value_name": "ZF0",
|
||||||
|
"value_type": 3,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 0,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "ZF1",
|
||||||
|
"value_type": 3,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 1,
|
||||||
|
"quantity": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "ZF2",
|
||||||
|
"value_type": 3,
|
||||||
|
"function_code": 3,
|
||||||
|
"start_address": 2,
|
||||||
|
"quantity": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,12 +1,14 @@
|
||||||
# OMRON_CP1L通信测试
|
# OMRON_CP1L/H通信测试
|
||||||
|
|
||||||
[TOC]
|
[TOC]
|
||||||
|
|
||||||
## 通信接线及参数设置
|
## 通信接线及参数设置
|
||||||
|
|
||||||
* 本体无接口,增加CP1W-CIF41网络板卡
|
* CP1L本体无接口,增加CP1W-CIF41网络板卡,CP1H自带网口,采用网线直连的方式
|
||||||
|
|
||||||
* FINS协议,PLC IP:192.168.250.31,Port:9600
|
* FINS协议,PLC IP:192.168.250.31,Port:9600
|
||||||
|
* 
|
||||||
|
* 
|
||||||
|
* 
|
||||||
|
|
||||||
## 存储区
|
## 存储区
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 190 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 204 KiB |
|
@ -0,0 +1,65 @@
|
||||||
|
# SCHNEIDER M241L通信测试
|
||||||
|
|
||||||
|
[TOC]
|
||||||
|
|
||||||
|
## 通信接线及参数设置
|
||||||
|
|
||||||
|
* 串口
|
||||||
|
* M241支持2路485串口,本次采用的是serial2。波特率:9600,数据位:8位,停止位:1位,校验:偶校验
|
||||||
|
|
||||||
|
## 存储区
|
||||||
|
|
||||||
|
- 存储区MW区。
|
||||||
|
|
||||||
|
## JSON配方设计
|
||||||
|
|
||||||
|
* 共测试BOOL,INT16共2种类型数据,以下为JSON文件解释。
|
||||||
|
|
||||||
|
- ```json
|
||||||
|
{
|
||||||
|
"device_id": 1, //设备ID默认是1,此参数无效
|
||||||
|
"device_name": "m241", //设备名称,自定义
|
||||||
|
"communication_type": 1, //通讯协议类型 0是以太网,1是串口
|
||||||
|
"serial_config": { //串口配置
|
||||||
|
"station": 1, //站号
|
||||||
|
"baud_rate": 9600, //波特率
|
||||||
|
"data_bits": 8, //数据位
|
||||||
|
"stop_bits": 1, //停止位
|
||||||
|
"check_mode": 3 //1无校验,2校验,3偶校验
|
||||||
|
},
|
||||||
|
"protocol_type": 3, //通讯协议,3代表modbus-tcp协议
|
||||||
|
"read_period": 100, //交互周期ms
|
||||||
|
"read_item_list": [
|
||||||
|
{
|
||||||
|
"value_name": "MW0", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3是读
|
||||||
|
"start_address": 0, //起始地址
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "MW1", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3是读
|
||||||
|
"start_address": 1, //起始地址偏移1位
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 通信测试
|
||||||
|
|
||||||
|
(1) 新增1个通信demo,命名为schneider_m241.c;
|
||||||
|
|
||||||
|
(2) 复制样例代码程序到schneider_m241.c文件中;
|
||||||
|
|
||||||
|
(3) void **ControlSCHNEIDERM241Test**(void) 更改函数名;
|
||||||
|
|
||||||
|
(4) PRIV_SHELL_CMD_FUNCTION(**ControlM241Test**, **Schneider M241 Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||||
|
|
||||||
|
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
# XINJE通信测试
|
||||||
|
|
||||||
|
[TOC]
|
||||||
|
|
||||||
|
## 通信接线及参数设置
|
||||||
|
|
||||||
|
* 网口
|
||||||
|
|
||||||
|
*Mosbus TCP协议,IP:192.168.250.32,Port:502
|
||||||
|
|
||||||
|
## 存储区
|
||||||
|
|
||||||
|
- 存储区M、D区。
|
||||||
|
|
||||||
|
## JSON配方设计
|
||||||
|
|
||||||
|
* 共测试BOOL,INT16共2种类型数据,以下为JSON文件解释。
|
||||||
|
|
||||||
|
- ```json
|
||||||
|
{
|
||||||
|
"device_id": 1, //设备ID默认是1,此参数无效
|
||||||
|
"device_name": "XDH", //设备名称,自定义
|
||||||
|
"communication_type": 0, //通讯协议类型 0是以太网,1是串口
|
||||||
|
"socket_config": { //以太网配置
|
||||||
|
"plc_ip": "192.168.250.32", //PLC的IP地址
|
||||||
|
"local_ip": "192.168.250.233", //矽达通IP地址设定
|
||||||
|
"gateway": "192.168.250.1", //矽达通的网关地址设定
|
||||||
|
"netmask": "255.255.255.0", //矽达通子网掩码设定
|
||||||
|
"port":502 //端口号设定
|
||||||
|
},
|
||||||
|
"protocol_type": 3, //通讯协议,3代表modbus-tcp协议
|
||||||
|
"read_period": 100, //交互周期ms
|
||||||
|
"read_item_list": [
|
||||||
|
{
|
||||||
|
"value_name": "MW0", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3是读
|
||||||
|
"start_address": 0, //起始地址
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value_name": "MW1", //变量名称,自定义
|
||||||
|
"value_type": 3, //变量类型,BOOL = 1,INT8 = 2,INT16,INT32,UINT8,UINT16,UINT32,DOUBLE,FLOAT = 9
|
||||||
|
"function_code": 3, //功能码。3是读
|
||||||
|
"start_address": 1, //起始地址偏移1位
|
||||||
|
"data_length": 1 //BOOL长度,默认是1,代表读取1个BOOL长度
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 通信测试
|
||||||
|
|
||||||
|
(1) 新增1个通信demo,命名为xinje_xdh.c;
|
||||||
|
|
||||||
|
(2) 复制样例代码程序到xinje_xdh.c文件中;
|
||||||
|
|
||||||
|
(3) void **ControlXINJEXDHTest**(void) 更改函数名;
|
||||||
|
|
||||||
|
(4) PRIV_SHELL_CMD_FUNCTION(**ControlXINJEXDHTest**, **Omron Plc Cp1l Demo**, PRIV_SHELL_CMD_MAIN_ATTR);更改测试指令;
|
||||||
|
|
||||||
|
(5) 剪裁配置完成后,用过烧写器下载至矽达通中,重启后完成测试。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += circular_area_app.c
|
CSRCS += circular_area_app.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := circular_area_app.c
|
SRC_FILES := circular_area_app.c
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
endif
|
endif
|
|
@ -1,11 +1,11 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += double_list.c single_list.c
|
CSRCS += double_list.c single_list.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := double_list.c single_list.c
|
SRC_FILES := double_list.c single_list.c
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
endif
|
endif
|
|
@ -1,6 +1,6 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
|
|
||||||
ifeq ($(CONFIG_K210_FFT_TEST), y)
|
ifeq ($(CONFIG_K210_FFT_TEST), y)
|
||||||
|
|
|
@ -155,7 +155,7 @@ void k210_fft_test(void)
|
||||||
cycle[FFT_SOFT][FFT_DIR_BACKWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000));
|
cycle[FFT_SOFT][FFT_DIR_BACKWARD]/(sysctl_clock_get_freq(SYSCTL_CLOCK_CPU)/1000000));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
void nuttx_k210_fft_test(void)
|
void nuttx_k210_fft_test(void)
|
||||||
{
|
{
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|
|
@ -71,7 +71,7 @@ void mnist_nnom(int argc, char **argv)
|
||||||
printf("Predicted label: %d\n", predic_label);
|
printf("Predicted label: %d\n", predic_label);
|
||||||
printf("Probability: %d%%\n", (int)(prob * 100));
|
printf("Probability: %d%%\n", (int)(prob * 100));
|
||||||
}
|
}
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
PRIV_SHELL_CMD_FUNCTION(mnist_nnom, a mnist_nnom test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
PRIV_SHELL_CMD_FUNCTION(mnist_nnom, a mnist_nnom test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
#endif
|
#endif
|
||||||
#ifdef __RT_THREAD_H__
|
#ifdef __RT_THREAD_H__
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
// #include <user_api.h>
|
// #include <user_api.h>
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
|
|
||||||
|
|
||||||
extern int FrameworkInit();
|
extern int FrameworkInit();
|
||||||
extern void ApplicationOtaTaskInit(void);
|
extern void ApplicationOtaTaskInit(void);
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|
|
@ -108,7 +108,7 @@ menu "sensor app"
|
||||||
bool "Using sensor HS300x apps"
|
bool "Using sensor HS300x apps"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
if ADD_NUTTX_FETURES
|
if ADD_NUTTX_FEATURES
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
@ -122,7 +122,7 @@ menu "sensor app"
|
||||||
bool "Using sensor HS300x apps"
|
bool "Using sensor HS300x apps"
|
||||||
default n
|
default n
|
||||||
|
|
||||||
if ADD_NUTTX_FETURES
|
if ADD_NUTTX_FEATURES
|
||||||
endif
|
endif
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
|
|
||||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
||||||
|
@ -64,7 +64,7 @@ ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES :=
|
SRC_FILES :=
|
||||||
|
|
||||||
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
ifeq ($(CONFIG_APPLICATION_SENSOR_HCHO_TB600B_WQ_HCHO1OS), y)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
SRC_DIR += WebNet_XiUOS
|
||||||
|
|
||||||
|
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1 +1 @@
|
||||||
Subproject commit 956eafa24bb65f5bb84d293ab35bf27084473edf
|
Subproject commit 60a8a500b93b47876c6eaff600e4cf2b8bf7b283
|
|
@ -5,16 +5,16 @@ menu "Framework"
|
||||||
default y
|
default y
|
||||||
choice
|
choice
|
||||||
prompt "select os features"
|
prompt "select os features"
|
||||||
default ADD_XIZI_FETURES
|
default ADD_XIZI_FEATURES
|
||||||
|
|
||||||
config ADD_XIZI_FETURES
|
config ADD_XIZI_FEATURES
|
||||||
bool "add xizi fetures"
|
bool "add xizi features"
|
||||||
|
|
||||||
config ADD_NUTTX_FETURES
|
config ADD_NUTTX_FEATURES
|
||||||
bool "add nuttx fetures"
|
bool "add nuttx features"
|
||||||
|
|
||||||
config ADD_RTTHREAD_FETURES
|
config ADD_RTTHREAD_FEATURES
|
||||||
bool "add rt_thread fetures"
|
bool "add rt_thread features"
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += framework_init.c
|
CSRCS += framework_init.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := framework_init.c
|
SRC_FILES := framework_init.c
|
||||||
SRC_DIR := transform_layer
|
SRC_DIR := transform_layer
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += adapter_4g.c
|
CSRCS += adapter_4g.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := adapter_4g.c
|
SRC_FILES := adapter_4g.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADAPTER_EC200T),y)
|
ifeq ($(CONFIG_ADAPTER_EC200T),y)
|
||||||
|
|
|
@ -2,7 +2,7 @@ config ADAPTER_4G_EC200T
|
||||||
string "EC200T adapter name"
|
string "EC200T adapter name"
|
||||||
default "ec200t"
|
default "ec200t"
|
||||||
|
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config ADAPTER_EC200T_USING_PWRKEY
|
config ADAPTER_EC200T_USING_PWRKEY
|
||||||
bool "EC200T using PWRKEY pin number"
|
bool "EC200T using PWRKEY pin number"
|
||||||
default n
|
default n
|
||||||
|
@ -37,7 +37,7 @@ if ADD_XIZI_FETURES
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_NUTTX_FETURES
|
if ADD_NUTTX_FEATURES
|
||||||
config ADAPTER_EC200T_USING_PWRKEY
|
config ADAPTER_EC200T_USING_PWRKEY
|
||||||
bool "EC200T using PWRKEY pin number"
|
bool "EC200T using PWRKEY pin number"
|
||||||
default n
|
default n
|
||||||
|
@ -72,7 +72,7 @@ if ADD_NUTTX_FETURES
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_RTTHREAD_FETURES
|
if ADD_RTTHREAD_FEATURES
|
||||||
config ADAPTER_EC200T_PWRKEY
|
config ADAPTER_EC200T_PWRKEY
|
||||||
int "EC200T PWRKEY pin number"
|
int "EC200T PWRKEY pin number"
|
||||||
default "97"
|
default "97"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += ec200t.c
|
CSRCS += ec200t.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := ec200t.c
|
SRC_FILES := ec200t.c
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -142,7 +142,7 @@ out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_RTTHREAD_FETURES
|
#ifdef ADD_RTTHREAD_FEATURES
|
||||||
static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args){ return 0;}
|
static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args){ return 0;}
|
||||||
#else
|
#else
|
||||||
static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
|
static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
|
||||||
|
@ -163,6 +163,8 @@ static int Ec200tIoctl(struct Adapter *adapter, int cmd, void *args)
|
||||||
serial_cfg.serial_parity_mode = PARITY_NONE;
|
serial_cfg.serial_parity_mode = PARITY_NONE;
|
||||||
serial_cfg.serial_bit_order = STOP_BITS_1;
|
serial_cfg.serial_bit_order = STOP_BITS_1;
|
||||||
serial_cfg.serial_invert_mode = NRZ_NORMAL;
|
serial_cfg.serial_invert_mode = NRZ_NORMAL;
|
||||||
|
//serial receive timeout 10s
|
||||||
|
serial_cfg.serial_timeout = 10000;
|
||||||
serial_cfg.is_ext_uart = 0;
|
serial_cfg.is_ext_uart = 0;
|
||||||
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT
|
#ifdef ADAPTER_EC200T_DRIVER_EXT_PORT
|
||||||
serial_cfg.is_ext_uart = 1;
|
serial_cfg.is_ext_uart = 1;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += adapter.c adapter_agent.c
|
CSRCS += adapter.c adapter_agent.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := adapter.c adapter_agent.c
|
SRC_FILES := adapter.c adapter_agent.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_CONNECTION_INDUSTRIAL_NETWORK),y)
|
ifeq ($(CONFIG_CONNECTION_INDUSTRIAL_NETWORK),y)
|
||||||
|
|
|
@ -53,6 +53,7 @@ extern "C" {
|
||||||
#define ADAPTER_NBIOT_NAME "nbiot"
|
#define ADAPTER_NBIOT_NAME "nbiot"
|
||||||
#define ADAPTER_WIFI_NAME "wifi"
|
#define ADAPTER_WIFI_NAME "wifi"
|
||||||
#define ADAPTER_ZIGBEE_NAME "zigbee"
|
#define ADAPTER_ZIGBEE_NAME "zigbee"
|
||||||
|
#define ADAPTER_MODBUS_RTU_NAME "modbus_rtu"
|
||||||
|
|
||||||
struct Adapter;
|
struct Adapter;
|
||||||
struct AdapterProductInfo;
|
struct AdapterProductInfo;
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
# include <user_api.h>
|
# include <user_api.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_RTTHREAD_FETURES
|
#ifdef ADD_RTTHREAD_FEATURES
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
#endif
|
#endif
|
||||||
#define AT_CMD_MAX_LEN 128
|
#define AT_CMD_MAX_LEN 128
|
||||||
|
@ -424,26 +424,26 @@ int DeleteATAgent(ATAgentType agent)
|
||||||
PrivClose(agent->fd);
|
PrivClose(agent->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
if (agent->lock.sem.semcount > 0) {
|
if (agent->lock.sem.semcount > 0) {
|
||||||
printf("delete agent lock = %d\n",agent->lock.sem.semcount);
|
printf("delete agent lock = %d\n",agent->lock.sem.semcount);
|
||||||
PrivMutexDelete(&agent->lock);
|
PrivMutexDelete(&agent->lock);
|
||||||
}
|
}
|
||||||
#elif defined ADD_RTTHREAD_FETURES
|
#elif defined ADD_RTTHREAD_FEATURES
|
||||||
#else
|
#else
|
||||||
if (agent->lock) {
|
if (agent->lock) {
|
||||||
printf("delete agent lock = %d\n",agent->lock);
|
printf("delete agent lock = %d\n",agent->lock);
|
||||||
PrivMutexDelete(&agent->lock);
|
PrivMutexDelete(&agent->lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
if (agent->entm_rx_notice) {
|
if (agent->entm_rx_notice) {
|
||||||
printf("delete agent entm_rx_notice = %d\n",agent->entm_rx_notice);
|
printf("delete agent entm_rx_notice = %d\n",agent->entm_rx_notice);
|
||||||
PrivSemaphoreDelete(&agent->entm_rx_notice);
|
PrivSemaphoreDelete(&agent->entm_rx_notice);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
if (agent->rsp_sem) {
|
if (agent->rsp_sem) {
|
||||||
printf("delete agent rsp_sem = %d\n",agent->rsp_sem);
|
printf("delete agent rsp_sem = %d\n",agent->rsp_sem);
|
||||||
PrivSemaphoreDelete(&agent->rsp_sem);
|
PrivSemaphoreDelete(&agent->rsp_sem);
|
||||||
|
@ -518,7 +518,7 @@ static int ATAgentInit(ATAgentType agent)
|
||||||
|
|
||||||
agent->receive_mode = DEFAULT_MODE;
|
agent->receive_mode = DEFAULT_MODE;
|
||||||
|
|
||||||
#ifdef ADD_NUTTX_FETURES
|
#ifdef ADD_NUTTX_FEATURES
|
||||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||||
attr.priority = 18;
|
attr.priority = 18;
|
||||||
attr.stacksize = 8192;
|
attr.stacksize = 8192;
|
||||||
|
|
|
@ -52,7 +52,7 @@ struct ATAgent
|
||||||
uint32 maintain_len;
|
uint32 maintain_len;
|
||||||
uint32 maintain_max;
|
uint32 maintain_max;
|
||||||
|
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
int lock;
|
int lock;
|
||||||
#else
|
#else
|
||||||
pthread_mutex_t lock;
|
pthread_mutex_t lock;
|
||||||
|
@ -63,7 +63,7 @@ struct ATAgent
|
||||||
char reply_end_last_char;
|
char reply_end_last_char;
|
||||||
char reply_end_char;
|
char reply_end_char;
|
||||||
uint32 reply_char_num;
|
uint32 reply_char_num;
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
int rsp_sem;
|
int rsp_sem;
|
||||||
#else
|
#else
|
||||||
sem_t rsp_sem;
|
sem_t rsp_sem;
|
||||||
|
@ -74,7 +74,7 @@ struct ATAgent
|
||||||
char entm_recv_buf[ENTM_RECV_MAX];
|
char entm_recv_buf[ENTM_RECV_MAX];
|
||||||
uint32 entm_recv_len;
|
uint32 entm_recv_len;
|
||||||
enum ReceiveMode receive_mode;
|
enum ReceiveMode receive_mode;
|
||||||
#ifdef ADD_XIZI_FETURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
int entm_rx_notice;
|
int entm_rx_notice;
|
||||||
#else
|
#else
|
||||||
sem_t entm_rx_notice;
|
sem_t entm_rx_notice;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += adapter_bluetooth.c
|
CSRCS += adapter_bluetooth.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := adapter_bluetooth.c
|
SRC_FILES := adapter_bluetooth.c
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADAPTER_HC08),y)
|
ifeq ($(CONFIG_ADAPTER_HC08),y)
|
||||||
|
|
|
@ -2,7 +2,7 @@ config ADAPTER_BLUETOOTH_HC08
|
||||||
string "HC08 adapter name"
|
string "HC08 adapter name"
|
||||||
default "hc08"
|
default "hc08"
|
||||||
|
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
config ADAPTER_HC08_RECV_BUFFER_SIZE
|
config ADAPTER_HC08_RECV_BUFFER_SIZE
|
||||||
int "HC08 recv data buffer size"
|
int "HC08 recv data buffer size"
|
||||||
default "128"
|
default "128"
|
||||||
|
@ -31,7 +31,7 @@ if ADD_XIZI_FETURES
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_NUTTX_FETURES
|
if ADD_NUTTX_FEATURES
|
||||||
|
|
||||||
config ADAPTER_HC08_WORK_ROLE
|
config ADAPTER_HC08_WORK_ROLE
|
||||||
string "HC08 work role M(MASTER) or S(SLAVER)"
|
string "HC08 work role M(MASTER) or S(SLAVER)"
|
||||||
|
@ -58,7 +58,7 @@ if ADD_NUTTX_FETURES
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_RTTHREAD_FETURES
|
if ADD_RTTHREAD_FEATURES
|
||||||
config ADAPTER_HC08_RECV_BUFFER_SIZE
|
config ADAPTER_HC08_RECV_BUFFER_SIZE
|
||||||
int "HC08 recv data buffer size"
|
int "HC08 recv data buffer size"
|
||||||
default "128"
|
default "128"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
include $(KERNEL_ROOT)/.config
|
include $(KERNEL_ROOT)/.config
|
||||||
ifeq ($(CONFIG_ADD_NUTTX_FETURES),y)
|
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||||
include $(APPDIR)/Make.defs
|
include $(APPDIR)/Make.defs
|
||||||
CSRCS += hc08.c
|
CSRCS += hc08.c
|
||||||
include $(APPDIR)/Application.mk
|
include $(APPDIR)/Application.mk
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_ADD_XIZI_FETURES),y)
|
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES := hc08.c
|
SRC_FILES := hc08.c
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
||||||
|
|
|
@ -353,7 +353,7 @@ static int Hc08Ioctl(struct Adapter *adapter, int cmd, void *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivTaskDelay(500);
|
PrivTaskDelay(500);
|
||||||
#ifdef ADD_RTTHREAD_FETURES
|
#ifdef ADD_RTTHREAD_FEATURES
|
||||||
//Step3 : show hc08 device info, hc08_get send "AT+RX" response device info
|
//Step3 : show hc08 device info, hc08_get send "AT+RX" response device info
|
||||||
char device_info[HC08_RESP_DEFAULT_SIZE * 2] = {0};
|
char device_info[HC08_RESP_DEFAULT_SIZE * 2] = {0};
|
||||||
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_GET_DEVICE_INFO, NULL, device_info) < 0) {
|
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_GET_DEVICE_INFO, NULL, device_info) < 0) {
|
||||||
|
@ -369,7 +369,7 @@ static int Hc08Ioctl(struct Adapter *adapter, int cmd, void *args)
|
||||||
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_GET_LUUID, NULL, NULL) < 0) {
|
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_GET_LUUID, NULL, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#ifdef ADD_RTTHREAD_FETURES
|
#ifdef ADD_RTTHREAD_FEATURES
|
||||||
uint32_t suuid=1234;
|
uint32_t suuid=1234;
|
||||||
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_SET_SUUID, &luuid, NULL) < 0) {
|
if (Hc08AtConfigure(adapter->agent, HC08_AT_CMD_SET_SUUID, &luuid, NULL) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -2,7 +2,7 @@ config ADAPTER_ETHERNET_HFA21
|
||||||
string "HFA21 ETHERNET adapter name"
|
string "HFA21 ETHERNET adapter name"
|
||||||
default "hfa21_ethernet"
|
default "hfa21_ethernet"
|
||||||
|
|
||||||
if ADD_XIZI_FETURES
|
if ADD_XIZI_FEATURES
|
||||||
|
|
||||||
config ADAPTER_HFA21_DRIVER_EXTUART
|
config ADAPTER_HFA21_DRIVER_EXTUART
|
||||||
bool "Using extra uart to support ethernet"
|
bool "Using extra uart to support ethernet"
|
||||||
|
@ -24,11 +24,11 @@ if ADD_XIZI_FETURES
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_NUTTX_FETURES
|
if ADD_NUTTX_FEATURES
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ADD_RTTHREAD_FETURES
|
if ADD_RTTHREAD_FEATURES
|
||||||
config ADAPTER_HFA21_DRIVER
|
config ADAPTER_HFA21_DRIVER
|
||||||
string "HFA21 device uart driver path"
|
string "HFA21 device uart driver path"
|
||||||
default "/dev/uart3"
|
default "/dev/uart3"
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* FreeModbus Libary: BARE Demo Application
|
||||||
|
* Copyright (C) 2006 Christian Walter <wolti@sil.at>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* File: $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
|
#include "mb.h"
|
||||||
|
#include "mbport.h"
|
||||||
|
|
||||||
|
/* ----------------------- Defines ------------------------------------------*/
|
||||||
|
#define REG_INPUT_START 1000
|
||||||
|
#define REG_INPUT_NREGS 4
|
||||||
|
|
||||||
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
|
static USHORT usRegInputStart = REG_INPUT_START;
|
||||||
|
static USHORT usRegInputBuf[REG_INPUT_NREGS];
|
||||||
|
|
||||||
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
int
|
||||||
|
main( void )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus;
|
||||||
|
|
||||||
|
eStatus = eMBInit( MB_RTU, 0x0A, 0, 38400, MB_PAR_EVEN );
|
||||||
|
|
||||||
|
/* Enable the Modbus Protocol Stack. */
|
||||||
|
eStatus = eMBEnable( );
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
( void )eMBPoll( );
|
||||||
|
|
||||||
|
/* Here we simply count the number of poll cycles. */
|
||||||
|
usRegInputBuf[0]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
int iRegIndex;
|
||||||
|
|
||||||
|
if( ( usAddress >= REG_INPUT_START )
|
||||||
|
&& ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
|
||||||
|
{
|
||||||
|
iRegIndex = ( int )( usAddress - usRegInputStart );
|
||||||
|
while( usNRegs > 0 )
|
||||||
|
{
|
||||||
|
*pucRegBuffer++ =
|
||||||
|
( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
|
||||||
|
*pucRegBuffer++ =
|
||||||
|
( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
|
||||||
|
iRegIndex++;
|
||||||
|
usNRegs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eStatus = MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs,
|
||||||
|
eMBRegisterMode eMode )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,
|
||||||
|
eMBRegisterMode eMode )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
|
||||||
|
{
|
||||||
|
return MB_ENOREG;
|
||||||
|
}
|
|
@ -0,0 +1,485 @@
|
||||||
|
/*
|
||||||
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
|
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- System includes ----------------------------------*/
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
/* ----------------------- Platform includes --------------------------------*/
|
||||||
|
#include "port.h"
|
||||||
|
|
||||||
|
/* ----------------------- Modbus includes ----------------------------------*/
|
||||||
|
#include "mb.h"
|
||||||
|
#include "mbconfig.h"
|
||||||
|
#include "mbascii.h"
|
||||||
|
#include "mbframe.h"
|
||||||
|
|
||||||
|
#include "mbcrc.h"
|
||||||
|
#include "mbport.h"
|
||||||
|
|
||||||
|
#if MB_ASCII_ENABLED > 0
|
||||||
|
|
||||||
|
/* ----------------------- Defines ------------------------------------------*/
|
||||||
|
#define MB_ASCII_DEFAULT_CR '\r' /*!< Default CR character for Modbus ASCII. */
|
||||||
|
#define MB_ASCII_DEFAULT_LF '\n' /*!< Default LF character for Modbus ASCII. */
|
||||||
|
#define MB_SER_PDU_SIZE_MIN 3 /*!< Minimum size of a Modbus ASCII frame. */
|
||||||
|
#define MB_SER_PDU_SIZE_MAX 256 /*!< Maximum size of a Modbus ASCII frame. */
|
||||||
|
#define MB_SER_PDU_SIZE_LRC 1 /*!< Size of LRC field in PDU. */
|
||||||
|
#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
|
||||||
|
#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
|
||||||
|
|
||||||
|
/* ----------------------- Type definitions ---------------------------------*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STATE_RX_IDLE, /*!< Receiver is in idle state. */
|
||||||
|
STATE_RX_RCV, /*!< Frame is beeing received. */
|
||||||
|
STATE_RX_WAIT_EOF /*!< Wait for End of Frame. */
|
||||||
|
} eMBRcvState;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
STATE_TX_IDLE, /*!< Transmitter is in idle state. */
|
||||||
|
STATE_TX_START, /*!< Starting transmission (':' sent). */
|
||||||
|
STATE_TX_DATA, /*!< Sending of data (Address, Data, LRC). */
|
||||||
|
STATE_TX_END, /*!< End of transmission. */
|
||||||
|
STATE_TX_NOTIFY /*!< Notify sender that the frame has been sent. */
|
||||||
|
} eMBSndState;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BYTE_HIGH_NIBBLE, /*!< Character for high nibble of byte. */
|
||||||
|
BYTE_LOW_NIBBLE /*!< Character for low nibble of byte. */
|
||||||
|
} eMBBytePos;
|
||||||
|
|
||||||
|
/* ----------------------- Static functions ---------------------------------*/
|
||||||
|
static UCHAR prvucMBCHAR2BIN( UCHAR ucCharacter );
|
||||||
|
|
||||||
|
static UCHAR prvucMBBIN2CHAR( UCHAR ucByte );
|
||||||
|
|
||||||
|
static UCHAR prvucMBLRC( UCHAR * pucFrame, USHORT usLen );
|
||||||
|
|
||||||
|
/* ----------------------- Static variables ---------------------------------*/
|
||||||
|
static volatile eMBSndState eSndState;
|
||||||
|
static volatile eMBRcvState eRcvState;
|
||||||
|
|
||||||
|
/* We reuse the Modbus RTU buffer because only one buffer is needed and the
|
||||||
|
* RTU buffer is bigger. */
|
||||||
|
extern volatile UCHAR ucRTUBuf[];
|
||||||
|
static volatile UCHAR *ucASCIIBuf = ucRTUBuf;
|
||||||
|
|
||||||
|
static volatile USHORT usRcvBufferPos;
|
||||||
|
static volatile eMBBytePos eBytePos;
|
||||||
|
|
||||||
|
static volatile UCHAR *pucSndBufferCur;
|
||||||
|
static volatile USHORT usSndBufferCount;
|
||||||
|
|
||||||
|
static volatile UCHAR ucLRC;
|
||||||
|
static volatile UCHAR ucMBLFCharacter;
|
||||||
|
|
||||||
|
/* ----------------------- Start implementation -----------------------------*/
|
||||||
|
eMBErrorCode
|
||||||
|
eMBASCIIInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
( void )ucSlaveAddress;
|
||||||
|
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
|
ucMBLFCharacter = MB_ASCII_DEFAULT_LF;
|
||||||
|
|
||||||
|
if( xMBPortSerialInit( ucPort, ulBaudRate, 7, eParity ) != TRUE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EPORTERR;
|
||||||
|
}
|
||||||
|
else if( xMBPortTimersInit( MB_ASCII_TIMEOUT_SEC * 20000UL ) != TRUE )
|
||||||
|
{
|
||||||
|
eStatus = MB_EPORTERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eMBASCIIStart( void )
|
||||||
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
|
vMBPortSerialEnable( TRUE, FALSE );
|
||||||
|
eRcvState = STATE_RX_IDLE;
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
|
||||||
|
/* No special startup required for ASCII. */
|
||||||
|
( void )xMBPortEventPost( EV_READY );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eMBASCIIStop( void )
|
||||||
|
{
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
|
vMBPortSerialEnable( FALSE, FALSE );
|
||||||
|
vMBPortTimersDisable( );
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame, USHORT * pusLength )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
|
assert( usRcvBufferPos < MB_SER_PDU_SIZE_MAX );
|
||||||
|
|
||||||
|
/* Length and CRC check */
|
||||||
|
if( ( usRcvBufferPos >= MB_SER_PDU_SIZE_MIN )
|
||||||
|
&& ( prvucMBLRC( ( UCHAR * ) ucASCIIBuf, usRcvBufferPos ) == 0 ) )
|
||||||
|
{
|
||||||
|
/* Save the address field. All frames are passed to the upper layed
|
||||||
|
* and the decision if a frame is used is done there.
|
||||||
|
*/
|
||||||
|
*pucRcvAddress = ucASCIIBuf[MB_SER_PDU_ADDR_OFF];
|
||||||
|
|
||||||
|
/* Total length of Modbus-PDU is Modbus-Serial-Line-PDU minus
|
||||||
|
* size of address field and CRC checksum.
|
||||||
|
*/
|
||||||
|
*pusLength = ( USHORT )( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_LRC );
|
||||||
|
|
||||||
|
/* Return the start of the Modbus PDU to the caller. */
|
||||||
|
*pucFrame = ( UCHAR * ) & ucASCIIBuf[MB_SER_PDU_PDU_OFF];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
eMBErrorCode
|
||||||
|
eMBASCIISend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
|
||||||
|
{
|
||||||
|
eMBErrorCode eStatus = MB_ENOERR;
|
||||||
|
UCHAR usLRC;
|
||||||
|
|
||||||
|
ENTER_CRITICAL_SECTION( );
|
||||||
|
/* Check if the receiver is still in idle state. If not we where too
|
||||||
|
* slow with processing the received frame and the master sent another
|
||||||
|
* frame on the network. We have to abort sending the frame.
|
||||||
|
*/
|
||||||
|
if( eRcvState == STATE_RX_IDLE )
|
||||||
|
{
|
||||||
|
/* First byte before the Modbus-PDU is the slave address. */
|
||||||
|
pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
|
||||||
|
usSndBufferCount = 1;
|
||||||
|
|
||||||
|
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
|
||||||
|
pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress;
|
||||||
|
usSndBufferCount += usLength;
|
||||||
|
|
||||||
|
/* Calculate LRC checksum for Modbus-Serial-Line-PDU. */
|
||||||
|
usLRC = prvucMBLRC( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
|
||||||
|
ucASCIIBuf[usSndBufferCount++] = usLRC;
|
||||||
|
|
||||||
|
/* Activate the transmitter. */
|
||||||
|
eSndState = STATE_TX_START;
|
||||||
|
vMBPortSerialEnable( FALSE, TRUE );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eStatus = MB_EIO;
|
||||||
|
}
|
||||||
|
EXIT_CRITICAL_SECTION( );
|
||||||
|
return eStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
xMBASCIIReceiveFSM( void )
|
||||||
|
{
|
||||||
|
BOOL xNeedPoll = FALSE;
|
||||||
|
UCHAR ucByte;
|
||||||
|
UCHAR ucResult;
|
||||||
|
|
||||||
|
assert( eSndState == STATE_TX_IDLE );
|
||||||
|
|
||||||
|
( void )xMBPortSerialGetByte( ( CHAR * ) & ucByte );
|
||||||
|
switch ( eRcvState )
|
||||||
|
{
|
||||||
|
/* A new character is received. If the character is a ':' the input
|
||||||
|
* buffer is cleared. A CR-character signals the end of the data
|
||||||
|
* block. Other characters are part of the data block and their
|
||||||
|
* ASCII value is converted back to a binary representation.
|
||||||
|
*/
|
||||||
|
case STATE_RX_RCV:
|
||||||
|
/* Enable timer for character timeout. */
|
||||||
|
vMBPortTimersEnable( );
|
||||||
|
if( ucByte == ':' )
|
||||||
|
{
|
||||||
|
/* Empty receive buffer. */
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
usRcvBufferPos = 0;
|
||||||
|
}
|
||||||
|
else if( ucByte == MB_ASCII_DEFAULT_CR )
|
||||||
|
{
|
||||||
|
eRcvState = STATE_RX_WAIT_EOF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ucResult = prvucMBCHAR2BIN( ucByte );
|
||||||
|
switch ( eBytePos )
|
||||||
|
{
|
||||||
|
/* High nibble of the byte comes first. We check for
|
||||||
|
* a buffer overflow here. */
|
||||||
|
case BYTE_HIGH_NIBBLE:
|
||||||
|
if( usRcvBufferPos < MB_SER_PDU_SIZE_MAX )
|
||||||
|
{
|
||||||
|
ucASCIIBuf[usRcvBufferPos] = ( UCHAR )( ucResult << 4 );
|
||||||
|
eBytePos = BYTE_LOW_NIBBLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* not handled in Modbus specification but seems
|
||||||
|
* a resonable implementation. */
|
||||||
|
eRcvState = STATE_RX_IDLE;
|
||||||
|
/* Disable previously activated timer because of error state. */
|
||||||
|
vMBPortTimersDisable( );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BYTE_LOW_NIBBLE:
|
||||||
|
ucASCIIBuf[usRcvBufferPos] |= ucResult;
|
||||||
|
usRcvBufferPos++;
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_RX_WAIT_EOF:
|
||||||
|
if( ucByte == ucMBLFCharacter )
|
||||||
|
{
|
||||||
|
/* Disable character timeout timer because all characters are
|
||||||
|
* received. */
|
||||||
|
vMBPortTimersDisable( );
|
||||||
|
/* Receiver is again in idle state. */
|
||||||
|
eRcvState = STATE_RX_IDLE;
|
||||||
|
|
||||||
|
/* Notify the caller of eMBASCIIReceive that a new frame
|
||||||
|
* was received. */
|
||||||
|
xNeedPoll = xMBPortEventPost( EV_FRAME_RECEIVED );
|
||||||
|
}
|
||||||
|
else if( ucByte == ':' )
|
||||||
|
{
|
||||||
|
/* Empty receive buffer and back to receive state. */
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
usRcvBufferPos = 0;
|
||||||
|
eRcvState = STATE_RX_RCV;
|
||||||
|
|
||||||
|
/* Enable timer for character timeout. */
|
||||||
|
vMBPortTimersEnable( );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Frame is not okay. Delete entire frame. */
|
||||||
|
eRcvState = STATE_RX_IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_RX_IDLE:
|
||||||
|
if( ucByte == ':' )
|
||||||
|
{
|
||||||
|
/* Enable timer for character timeout. */
|
||||||
|
vMBPortTimersEnable( );
|
||||||
|
/* Reset the input buffers to store the frame. */
|
||||||
|
usRcvBufferPos = 0;;
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
eRcvState = STATE_RX_RCV;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xNeedPoll;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
xMBASCIITransmitFSM( void )
|
||||||
|
{
|
||||||
|
BOOL xNeedPoll = FALSE;
|
||||||
|
UCHAR ucByte;
|
||||||
|
|
||||||
|
assert( eRcvState == STATE_RX_IDLE );
|
||||||
|
switch ( eSndState )
|
||||||
|
{
|
||||||
|
/* Start of transmission. The start of a frame is defined by sending
|
||||||
|
* the character ':'. */
|
||||||
|
case STATE_TX_START:
|
||||||
|
ucByte = ':';
|
||||||
|
xMBPortSerialPutByte( ( CHAR )ucByte );
|
||||||
|
eSndState = STATE_TX_DATA;
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Send the data block. Each data byte is encoded as a character hex
|
||||||
|
* stream with the high nibble sent first and the low nibble sent
|
||||||
|
* last. If all data bytes are exhausted we send a '\r' character
|
||||||
|
* to end the transmission. */
|
||||||
|
case STATE_TX_DATA:
|
||||||
|
if( usSndBufferCount > 0 )
|
||||||
|
{
|
||||||
|
switch ( eBytePos )
|
||||||
|
{
|
||||||
|
case BYTE_HIGH_NIBBLE:
|
||||||
|
ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur >> 4 ) );
|
||||||
|
xMBPortSerialPutByte( ( CHAR ) ucByte );
|
||||||
|
eBytePos = BYTE_LOW_NIBBLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BYTE_LOW_NIBBLE:
|
||||||
|
ucByte = prvucMBBIN2CHAR( ( UCHAR )( *pucSndBufferCur & 0x0F ) );
|
||||||
|
xMBPortSerialPutByte( ( CHAR )ucByte );
|
||||||
|
pucSndBufferCur++;
|
||||||
|
eBytePos = BYTE_HIGH_NIBBLE;
|
||||||
|
usSndBufferCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xMBPortSerialPutByte( MB_ASCII_DEFAULT_CR );
|
||||||
|
eSndState = STATE_TX_END;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Finish the frame by sending a LF character. */
|
||||||
|
case STATE_TX_END:
|
||||||
|
xMBPortSerialPutByte( ( CHAR )ucMBLFCharacter );
|
||||||
|
/* We need another state to make sure that the CR character has
|
||||||
|
* been sent. */
|
||||||
|
eSndState = STATE_TX_NOTIFY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Notify the task which called eMBASCIISend that the frame has
|
||||||
|
* been sent. */
|
||||||
|
case STATE_TX_NOTIFY:
|
||||||
|
eSndState = STATE_TX_IDLE;
|
||||||
|
xNeedPoll = xMBPortEventPost( EV_FRAME_SENT );
|
||||||
|
|
||||||
|
/* Disable transmitter. This prevents another transmit buffer
|
||||||
|
* empty interrupt. */
|
||||||
|
vMBPortSerialEnable( TRUE, FALSE );
|
||||||
|
eSndState = STATE_TX_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* We should not get a transmitter event if the transmitter is in
|
||||||
|
* idle state. */
|
||||||
|
case STATE_TX_IDLE:
|
||||||
|
/* enable receiver/disable transmitter. */
|
||||||
|
vMBPortSerialEnable( TRUE, FALSE );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xNeedPoll;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
xMBASCIITimerT1SExpired( void )
|
||||||
|
{
|
||||||
|
switch ( eRcvState )
|
||||||
|
{
|
||||||
|
/* If we have a timeout we go back to the idle state and wait for
|
||||||
|
* the next frame.
|
||||||
|
*/
|
||||||
|
case STATE_RX_RCV:
|
||||||
|
case STATE_RX_WAIT_EOF:
|
||||||
|
eRcvState = STATE_RX_IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert( ( eRcvState == STATE_RX_RCV ) || ( eRcvState == STATE_RX_WAIT_EOF ) );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
vMBPortTimersDisable( );
|
||||||
|
|
||||||
|
/* no context switch required. */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static UCHAR
|
||||||
|
prvucMBCHAR2BIN( UCHAR ucCharacter )
|
||||||
|
{
|
||||||
|
if( ( ucCharacter >= '0' ) && ( ucCharacter <= '9' ) )
|
||||||
|
{
|
||||||
|
return ( UCHAR )( ucCharacter - '0' );
|
||||||
|
}
|
||||||
|
else if( ( ucCharacter >= 'A' ) && ( ucCharacter <= 'F' ) )
|
||||||
|
{
|
||||||
|
return ( UCHAR )( ucCharacter - 'A' + 0x0A );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UCHAR
|
||||||
|
prvucMBBIN2CHAR( UCHAR ucByte )
|
||||||
|
{
|
||||||
|
if( ucByte <= 0x09 )
|
||||||
|
{
|
||||||
|
return ( UCHAR )( '0' + ucByte );
|
||||||
|
}
|
||||||
|
else if( ( ucByte >= 0x0A ) && ( ucByte <= 0x0F ) )
|
||||||
|
{
|
||||||
|
return ( UCHAR )( ucByte - 0x0A + 'A' );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Programming error. */
|
||||||
|
assert( 0 );
|
||||||
|
}
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static UCHAR
|
||||||
|
prvucMBLRC( UCHAR * pucFrame, USHORT usLen )
|
||||||
|
{
|
||||||
|
UCHAR ucLRC = 0; /* LRC char initialized */
|
||||||
|
|
||||||
|
while( usLen-- )
|
||||||
|
{
|
||||||
|
ucLRC += *pucFrame++; /* Add buffer byte without carry */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return twos complement */
|
||||||
|
ucLRC = ( UCHAR ) ( -( ( CHAR ) ucLRC ) );
|
||||||
|
return ucLRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* FreeModbus Libary: A portable Modbus implementation for Modbus ASCII/RTU.
|
||||||
|
* Copyright (c) 2006-2018 Christian Walter <cwalter@embedded-solutions.at>
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MB_ASCII_H
|
||||||
|
#define _MB_ASCII_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
PR_BEGIN_EXTERN_C
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MB_ASCII_ENABLED > 0
|
||||||
|
eMBErrorCode eMBASCIIInit( UCHAR slaveAddress, UCHAR ucPort,
|
||||||
|
ULONG ulBaudRate, eMBParity eParity );
|
||||||
|
void eMBASCIIStart( void );
|
||||||
|
void eMBASCIIStop( void );
|
||||||
|
|
||||||
|
eMBErrorCode eMBASCIIReceive( UCHAR * pucRcvAddress, UCHAR ** pucFrame,
|
||||||
|
USHORT * pusLength );
|
||||||
|
eMBErrorCode eMBASCIISend( UCHAR slaveAddress, const UCHAR * pucFrame,
|
||||||
|
USHORT usLength );
|
||||||
|
BOOL xMBASCIIReceiveFSM( void );
|
||||||
|
BOOL xMBASCIITransmitFSM( void );
|
||||||
|
BOOL xMBASCIITimerT1SExpired( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
PR_END_EXTERN_C
|
||||||
|
#endif
|
||||||
|
#endif
|