Merge branch '2023_open_source_contest' of https://gitlink.org.cn/xuos/xiuos into 2023_open_source_contest
|
@ -36,5 +36,9 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
SRC_DIR += control_app
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APP_USING_WEBNET),y)
|
||||
SRC_DIR += webnet
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
|
@ -72,6 +72,24 @@ menu "test app"
|
|||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_SOCKET
|
||||
select BSP_USING_LWIP
|
||||
bool "Config test socket(lwip)"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_UART
|
||||
select BSP_USING_UART
|
||||
select BSP_USING_UART6
|
||||
bool "Config test uart"
|
||||
default n
|
||||
if USER_TEST_UART
|
||||
if ADD_XIZI_FEATURES
|
||||
config UART_DEV_DRIVER
|
||||
string "Set uart dev path"
|
||||
default "/dev/usart6_dev6"
|
||||
endif
|
||||
endif
|
||||
|
||||
menuconfig USER_TEST_RS485
|
||||
select BSP_USING_UART
|
||||
select BSP_USING_GPIO
|
||||
|
@ -252,6 +270,10 @@ menu "test app"
|
|||
bool "Config test red black tree"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_MODBUS_TCP
|
||||
bool "Config test modbus_tcp"
|
||||
default n
|
||||
|
||||
menuconfig USER_TEST_WEBSERVER
|
||||
bool "Config test webserver"
|
||||
default n
|
||||
|
|
|
@ -49,6 +49,10 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
SRC_FILES += test_i2c.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_UART),y)
|
||||
SRC_FILES += test_uart.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_GPIO),y)
|
||||
SRC_FILES += test_gpio.c
|
||||
endif
|
||||
|
@ -111,8 +115,16 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
|||
|
||||
ifeq ($(CONFIG_USER_TEST_RBTREE),y)
|
||||
SRC_FILES += test_rbtree/test_rbtree.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_SOCKET),y)
|
||||
SRC_FILES += test_socket.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_MODBUS_TCP),y)
|
||||
SRC_DIR += test_modbus_tcp
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_USER_TEST_WEBSERVER),y)
|
||||
SRC_FILES += test_webserver/test_webserver.c
|
||||
endif
|
||||
|
|
|
@ -26,9 +26,8 @@
|
|||
void TestAdc(void)
|
||||
{
|
||||
int adc_fd;
|
||||
uint8 adc_channel = 0x0;
|
||||
uint16 adc_sample, adc_value_decimal = 0;
|
||||
float adc_value;
|
||||
uint8 adc_channel = 0x1;
|
||||
uint16 adc_sample = 0;
|
||||
|
||||
adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR);
|
||||
if (adc_fd < 0) {
|
||||
|
@ -45,13 +44,11 @@ void TestAdc(void)
|
|||
return;
|
||||
}
|
||||
|
||||
PrivRead(adc_fd, &adc_sample, 2);
|
||||
|
||||
adc_value = (float)adc_sample * (3.3 / 4096);
|
||||
|
||||
adc_value_decimal = (adc_value - (uint16)adc_value) * 1000;
|
||||
|
||||
printf("adc sample %u value integer %u decimal %u\n", adc_sample, (uint16)adc_value, adc_value_decimal);
|
||||
for (int i = 0; i < 10; i ++) {
|
||||
PrivRead(adc_fd, &adc_sample, 2);
|
||||
printf("adc sample %u mv\n", adc_sample);
|
||||
PrivTaskDelay(500);
|
||||
}
|
||||
|
||||
PrivClose(adc_fd);
|
||||
|
||||
|
|
|
@ -22,17 +22,16 @@
|
|||
#include <transform.h>
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
||||
void TestDac(void)
|
||||
static pthread_t test_dac_task;
|
||||
|
||||
static void *TestDacTask(void *parameter)
|
||||
{
|
||||
int dac_fd;
|
||||
uint16 dac_set_value = 800;
|
||||
uint16 dac_sample, dac_value_decimal = 0;
|
||||
float dac_value;
|
||||
uint16 dac_set_value = 4096 * 10;//sin length
|
||||
|
||||
dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR);
|
||||
if (dac_fd < 0) {
|
||||
KPrintf("open dac fd error %d\n", dac_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
|
@ -41,20 +40,24 @@ void TestDac(void)
|
|||
if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) {
|
||||
KPrintf("ioctl dac fd error %d\n", dac_fd);
|
||||
PrivClose(dac_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
PrivRead(dac_fd, &dac_sample, 2);
|
||||
|
||||
dac_value = (float)dac_sample * (3.3 / 4096);//Vref+ need to be 3.3V
|
||||
|
||||
dac_value_decimal = (dac_value - (uint16)dac_value) * 1000;
|
||||
|
||||
printf("dac sample %u value integer %u decimal %u\n", dac_sample, (uint16)dac_value, dac_value_decimal);
|
||||
while (1) {
|
||||
//start dac output sin
|
||||
PrivWrite(dac_fd, NULL, 0);
|
||||
}
|
||||
|
||||
PrivClose(dac_fd);
|
||||
}
|
||||
|
||||
return;
|
||||
void TestDac(void)
|
||||
{
|
||||
pthread_attr_t tid;
|
||||
tid.schedparam.sched_priority = 20;
|
||||
tid.stacksize = 4096;
|
||||
|
||||
PrivTaskCreate(&test_dac_task, &tid, &TestDacTask, NULL);
|
||||
PrivTaskStartup(&test_dac_task);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TestDac, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
#endif
|
|
@ -28,11 +28,11 @@
|
|||
static uint16_t pin_fd=0;
|
||||
static struct PinStat pin_led;
|
||||
|
||||
void ledflip(void *parameter)
|
||||
void LedFlip(void *parameter)
|
||||
{
|
||||
pin_led.pin = BSP_LED_PIN;
|
||||
pin_led.val = !pin_led.val;
|
||||
PrivWrite(pin_fd,&pin_led,NULL_PARAMETER);
|
||||
PrivWrite(pin_fd, &pin_led, NULL_PARAMETER);
|
||||
}
|
||||
|
||||
void TestHwTimer(void)
|
||||
|
@ -40,22 +40,22 @@ void TestHwTimer(void)
|
|||
x_ticks_t period = 100000;
|
||||
|
||||
pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR);
|
||||
if(pin_fd<0){
|
||||
if(pin_fd<0) {
|
||||
printf("open pin fd error:%d\n",pin_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
int timer_fd = PrivOpen(HWTIMER_TIMER_DEV_DRIVER, O_RDWR);
|
||||
if(timer_fd<0){
|
||||
if(timer_fd<0) {
|
||||
printf("open timer fd error:%d\n",timer_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
//config led pin in board
|
||||
struct PinParam parameter;
|
||||
parameter.cmd = GPIO_CONFIG_MODE;
|
||||
parameter.pin = BSP_LED_PIN;
|
||||
parameter.mode = GPIO_CFG_OUTPUT;
|
||||
struct PinParam parameter;
|
||||
parameter.cmd = GPIO_CONFIG_MODE;
|
||||
parameter.pin = BSP_LED_PIN;
|
||||
parameter.mode = GPIO_CFG_OUTPUT;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
ioctl_cfg.ioctl_driver_type = PIN_TYPE;
|
||||
|
@ -68,7 +68,7 @@ void TestHwTimer(void)
|
|||
}
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = TIME_TYPE;
|
||||
ioctl_cfg.args = (void *)&ledflip;
|
||||
ioctl_cfg.args = (void *)&LedFlip;
|
||||
if (0 != PrivIoctl(timer_fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("timer pin fd error %d\n", pin_fd);
|
||||
PrivClose(pin_fd);
|
||||
|
@ -82,13 +82,10 @@ void TestHwTimer(void)
|
|||
return;
|
||||
}
|
||||
|
||||
while(1){
|
||||
while(1) {
|
||||
|
||||
}
|
||||
|
||||
// int32 timer_handle = KCreateTimer("LED on and off by 1s",&ledflip,&pin_fd,period,TIMER_TRIGGER_PERIODIC);
|
||||
|
||||
// KTimerStartRun(timer_handle);
|
||||
PrivClose(pin_fd);
|
||||
PrivClose(timer_fd);
|
||||
}
|
||||
|
|
|
@ -24,18 +24,16 @@
|
|||
|
||||
#define I2C_SLAVE_ADDRESS 0x0012U
|
||||
|
||||
void TestI2C(void)
|
||||
int OpenIic(void)
|
||||
{
|
||||
// config IIC pin(SCL:34.SDA:35) in menuconfig
|
||||
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
|
||||
if (iic_fd < 0)
|
||||
{
|
||||
printf("open iic_fd fd error:%d\n", iic_fd);
|
||||
return;
|
||||
printf("[TestI2C] Open iic_fd fd error: %d\n", iic_fd);
|
||||
return -ERROR;
|
||||
}
|
||||
printf("IIC open successful!\n");
|
||||
printf("[TestI2C] IIC open successful!\n");
|
||||
|
||||
// init iic
|
||||
uint16 iic_address = I2C_SLAVE_ADDRESS;
|
||||
|
||||
struct PrivIoctlCfg ioctl_cfg;
|
||||
|
@ -44,28 +42,55 @@ void TestI2C(void)
|
|||
|
||||
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
|
||||
{
|
||||
printf("ioctl iic fd error %d\n", iic_fd);
|
||||
printf("[TestI2C] Ioctl iic fd error %d\n", iic_fd);
|
||||
PrivClose(iic_fd);
|
||||
return;
|
||||
return -ERROR;
|
||||
}
|
||||
printf("IIC configure successful!\n");
|
||||
|
||||
// I2C read and write
|
||||
char tmp_buff[100];
|
||||
while (1)
|
||||
{
|
||||
PrivTaskDelay(1000);
|
||||
PrivWrite(iic_fd, "Hello World!\n", sizeof("Hello World!\n"));
|
||||
printf("msg send:%s\n", "Hello World!\n");
|
||||
PrivTaskDelay(1000);
|
||||
memset(tmp_buff, 0, sizeof(tmp_buff));
|
||||
PrivRead(iic_fd, tmp_buff, sizeof(tmp_buff));
|
||||
printf("msg recv:%s\n", tmp_buff);
|
||||
return iic_fd;
|
||||
}
|
||||
|
||||
static const int nr_transmit = 15;
|
||||
|
||||
void TestMasterI2c(void)
|
||||
{
|
||||
char recv_buff[13] = { 0 };
|
||||
|
||||
int iic_fd = OpenIic();
|
||||
if (iic_fd < 0) {
|
||||
printf("[%s] Error open iic\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) {
|
||||
// wait if you like.
|
||||
PrivTaskDelay(500);
|
||||
memset(recv_buff, 0, sizeof(recv_buff));
|
||||
PrivRead(iic_fd, recv_buff, sizeof(recv_buff));
|
||||
printf("[%s] Msg recv: %s\n", __func__, recv_buff);
|
||||
}
|
||||
|
||||
PrivClose(iic_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
void TestSlaveI2c(void)
|
||||
{
|
||||
char send_buff[] = "Hello, World";
|
||||
|
||||
int iic_fd = OpenIic();
|
||||
|
||||
for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) {
|
||||
// wait if you like.
|
||||
PrivTaskDelay(500);
|
||||
PrivWrite(iic_fd, send_buff, sizeof(send_buff));
|
||||
printf("[%s] Msg send: %s\n", __func__, send_buff);
|
||||
}
|
||||
|
||||
PrivClose(iic_fd);
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestMasterI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
PRIV_SHELL_CMD_FUNCTION(TestSlaveI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,11 @@
|
|||
ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||
SRC_FILES := modbus_tcp.c test_modbus_tcp.c
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
endif
|
||||
|
||||
include $(KERNEL_ROOT)/.config
|
||||
ifeq ($(CONFIG_ADD_NUTTX_FEATURES),y)
|
||||
include $(APPDIR)/Make.defs
|
||||
CSRCS += modbus_tcp.c test_modbus_tcp.c
|
||||
include $(APPDIR)/Application.mk
|
||||
endif
|
|
@ -0,0 +1,340 @@
|
|||
# ##modbus-tcp##
|
||||
|
||||
## 1. 简介
|
||||
|
||||
在xiuos平台实现modbusTCP协议,包括协议报文组装、解析和数据传输,支持主从通信。
|
||||
|
||||
## 2. 数据结构设计说明
|
||||
|
||||
### 2.1 数据结构定义
|
||||
|
||||
首先,需要定义设备存储区的结构体,包括两种存储类型,16位的寄存器和线圈。
|
||||
|
||||
```c
|
||||
//定义存储区结构体
|
||||
typedef struct MbMemory
|
||||
{
|
||||
coils8_t*rcoil_mem;
|
||||
reg_t*rreg_mem;
|
||||
coils8_t*rwcoil_mem;
|
||||
reg_t*rwreg_mem;
|
||||
}MBmemoryType;
|
||||
```
|
||||
|
||||
然后便是关于ModbusTCP协议相关的结构体定义,包括MBAP和PDU,后续数据区视情况而定,长短不固定。
|
||||
|
||||
```c
|
||||
//协议的固定部分为12个字节,当功能码为写多个数据时,后续还有不定长的数据部分
|
||||
typedef struct mbap
|
||||
{
|
||||
//MbapType
|
||||
u16_t tid;
|
||||
u16_t pid;
|
||||
u16_t len;
|
||||
u8_t uid;
|
||||
|
||||
/* data */
|
||||
}MbapType;
|
||||
|
||||
typedef struct pdu
|
||||
{
|
||||
u8_t func;
|
||||
|
||||
u16_t addr;
|
||||
|
||||
u8_t operand1;
|
||||
u8_t operand2;
|
||||
/* data */
|
||||
}PduType;
|
||||
```
|
||||
|
||||
### 2.1 从设备请求解析和响应部分
|
||||
|
||||
主要定义请求的解析器结构,以及每种功能码对应的解析函数,和发送响应的函数。
|
||||
|
||||
```c
|
||||
//定义解析器结构体
|
||||
typedef struct mbparser
|
||||
{
|
||||
int (*func_set[20])(MBmemoryType*,int,MbapType*,PduType*,u8_t**resp);
|
||||
}MbParserType;
|
||||
|
||||
//功能码解析函数
|
||||
int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
|
||||
|
||||
/**
|
||||
* @description: 制作响应报文
|
||||
* @param {MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len}
|
||||
* @return {}
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
void MakeResponse(MbapType*,PduType*,u8_t**,u16_t);
|
||||
|
||||
/**
|
||||
* @Description: 发送响应报文
|
||||
* @param {int} fd 套接字对应文件描述符
|
||||
* @param {u16_t} n 报文大小
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:24:55
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int SendResponse(int fd,u8_t**buf,u16_t n);
|
||||
|
||||
|
||||
```
|
||||
|
||||
### 2.2 主设备的请求包装和发送部分
|
||||
|
||||
```c
|
||||
/**
|
||||
* @Description: 读取键盘输入,并生成请求报文
|
||||
* @param {u8_t} flag
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:25:26
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int GenerateModbusRequest(MbapType*,PduType*,u8_t flag,u8_t**request);
|
||||
|
||||
/**
|
||||
* @Description: 发送请求报文
|
||||
* @param {int fd,u8_t**request,int n}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:26:10
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
void SendModbus(int fd,u8_t**request,int n);
|
||||
|
||||
/**
|
||||
* @Description: 读取请求报文
|
||||
* @param {int fd,MbapType*mbap,PduType*pdu}
|
||||
* @return {void}
|
||||
* @Date: 2023-07-25 17:26:49
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
void GetRequest(int fd,MbapType*,PduType*);
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 3. 测试程序说明
|
||||
|
||||
modbusTCP协议基于TCP协议,因此其主从通信实际上是基于TCP的S/C通信,因此分为服务端和客户端。
|
||||
|
||||
服务端部分(从设备)程序实际上是一个被动接受请求报文的TCP服务器程序,除了一些基础参数的定义外,主要包括一个无限循环的服务程序,包括报文的接收,以及对存储区的操作,和生成发送响应。
|
||||
|
||||
```c
|
||||
static void *ModbusTcpServer(void *arg)
|
||||
{
|
||||
//设置IP和子网掩码网关
|
||||
u8_t uid=1;//定义从设备id和存储区
|
||||
|
||||
MBmemory mbm;//定义存储区
|
||||
if(mb_memory_init(&mbm)==-1)//初始化存储区,包括对四个存储区进行内存分配
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
MBparser mb_parser;//初始化功能码解析器
|
||||
MBparser_init(&mb_parser,MBTCP);//初始化解析器,将功能码对应函数注册
|
||||
|
||||
int fd=create_socket(PORT);//创建监听套接字
|
||||
if(fd==-1)return 0;
|
||||
|
||||
if (listen(fd, 10) != 0 ) {
|
||||
lw_error("Unable to listen\n");
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
//建立连接,因为每次接受的连接可能不是同一个设备发来的,因此需要把建立连接部分放在循环体内。
|
||||
struct sockaddr_in tcp_addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
printf("wait accept\n");
|
||||
int clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len);
|
||||
|
||||
if(clientfd==-1)
|
||||
{
|
||||
lw_error("Unable to listen\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
MBAP mbap;
|
||||
PDU pdu;
|
||||
read_mbtcp_MBAP(clientfd,&mbap);//读取数据前7字节为mbap初始化
|
||||
|
||||
if(mbap.uid!=uid){//检验是否为此从机
|
||||
close(clientfd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
read_mbtcp_PDU(clientfd,&pdu);//读取pdu和一些定长部分
|
||||
|
||||
printf("OP:%x\n",pdu.func);
|
||||
printf("ADDR:%x\n",pdu.addr);
|
||||
|
||||
u8_t** response_buf;//定义操作返回的指针
|
||||
u8_t buf_len=mb_parser.func_set[pdu.func](&mbm,clientfd,&mbap,&pdu,response_buf);//请求的解析和对存储区的操作
|
||||
|
||||
send_response(clientfd,response_buf,buf_len);//发送响应
|
||||
// return NULL;
|
||||
//执行操作
|
||||
|
||||
}
|
||||
close(clientfd);
|
||||
}
|
||||
close(fd);
|
||||
mb_memory_free(&mbm);//释放存储区
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
客户端部分(主设备)是一个主动发送请求的TCP客户端程序,主要包括一个接受键盘输入的循环体,可以接受用户输入的指令,然后包装成Modbus请求报文,并发送给ModbusTCP服务器,然后接受响应报文。
|
||||
|
||||
```c
|
||||
static void *ModbusTcpClient(void *arg)
|
||||
{
|
||||
u16_t counter=0;
|
||||
int fd = -1;
|
||||
int ret;
|
||||
|
||||
// lw_print("2023-05-27 Peng Guanhua\n");
|
||||
lw_print("%s start\n", __func__);
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);//定义服务器套接字
|
||||
if (fd < 0) {
|
||||
lw_print("Socket error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char tcp_ip_str[128]="192.168.31.148";//服务器ip和端口号
|
||||
u16_t tcp_socket_port=6000;
|
||||
|
||||
/*建立套接字连接*/
|
||||
printf("%s\n",tcp_ip_str);
|
||||
struct sockaddr_in tcp_sock;
|
||||
tcp_sock.sin_family = AF_INET;
|
||||
tcp_sock.sin_port = htons(tcp_socket_port);
|
||||
tcp_sock.sin_addr.s_addr = inet_addr(tcp_ip_str);
|
||||
printf("%s\n",tcp_ip_str);
|
||||
|
||||
memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero));
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr));
|
||||
|
||||
if (ret < 0) {
|
||||
lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lw_print("TCP connect %s:%d success, start.\n", tcp_ip_str, tcp_socket_port);
|
||||
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
MBAP mbap={counter,0,0,0};
|
||||
PDU pdu;
|
||||
u8_t*request;
|
||||
|
||||
int mesg_len=generate_modbus_request(&mbap,&pdu,MBTCP,&request);//此函数中接收键盘输入,并生成请求报文。
|
||||
send_modbus(fd,&request,mesg_len);//发送请求报文。
|
||||
get_response(fd,&mbap,&pdu);//接收响应报文,并显示
|
||||
counter++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 4. 运行结果
|
||||
|
||||
### 4.1 从设备通信测试
|
||||
|
||||
从设备测试,在终端上将TCP服务端程序打开,如图1,等待主设备的连接。
|
||||
|
||||

|
||||
|
||||
主设备采用Modbus Poll应用程序,建立TCP连接,如图2所示。
|
||||
|
||||

|
||||
|
||||
此时modbus poll程序便会不断的向从设备发送请求,如图3。
|
||||
|
||||

|
||||
|
||||
可以看到解析出的功能码、地址以及对应的响应报文,然后我们在modbus poll上修改一下存储区数据。如图4所示。
|
||||
|
||||

|
||||
|
||||
因为修改的是寄存器存储区的值,因此对应0x10功能码,然后看看从设备的反映。如图5所示。
|
||||
|
||||

|
||||
|
||||
可见成功收到功能码,并返回了响应的报文。
|
||||
|
||||

|
||||
|
||||
modbus poll显示响应成功,存储区已成功修改期望的值。
|
||||
|
||||

|
||||
|
||||
可见存储区已成功修改。
|
||||
|
||||
线圈部分的查询修改同理,不再赘述。
|
||||
|
||||
### 4.2主设备通信测试
|
||||
|
||||
首先打开modbus slave应用程序,用以作为从设备,然后将存储区数据修改,用以测试,并打开TCP端口,等待主设备的连接,如图8所示。
|
||||
|
||||

|
||||
|
||||
同样在终端打开从设备程序,从设备的ip,port在源码中已定义好,所以打开时已经连接上,如图9所示。
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
开始输入从设备id,功能码,以及其他信息用以生成请求报文。
|
||||
|
||||

|
||||
|
||||
如图10所示,输入功能码3,对应读取寄存器功能,地址从0开始,数量4,然后便会生成请求报文,然后发送,结果如图11所示。
|
||||
|
||||

|
||||
|
||||
可见,已成功查询到寄存器的值。
|
||||
|
||||
然后测试写入功能,输入功能码15(0xf),对应写入多个线圈功能,如图12,modbus slave对应的响应结果如图13所示。
|
||||
|
||||

|
||||
|
||||
写入线圈的值为5个,分别为1 0 1 0 1。发送成功后,modbus salve中显示如图13所示。
|
||||
|
||||

|
||||
|
||||
可见,已成功修改。
|
||||
|
||||
其他功能码测试过程类似,不再赘述。
|
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,729 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @Description:包含modbusTCP请求报文的包装解析,以及报文收发,和每种功能码对应操作的实现。
|
||||
* @Version: V1.0.0
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @Date: 2023-05-24 04:00:02
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 16:36:53
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include"modbus_tcp.h"
|
||||
|
||||
u16_t Func0x_response_length[20]=
|
||||
{
|
||||
0,9,9,9,9,12,12,0,0,0,0,0,0,0,0,12,12
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @description: 初始化功能码解析器
|
||||
* @param {MbParserType*}mbp {u8_t} type
|
||||
* @return {void}
|
||||
* @Date: 2023-07-25 16:59:23
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
void MbparserInit(MbParserType*mbp,u8_t type)
|
||||
{
|
||||
mbp->func_set[R_RW_COIL]=FuncReadRwCoilX01;
|
||||
mbp->func_set[R_R_COIL]=FuncReadRCoilX02;
|
||||
mbp->func_set[R_RW_REG]=FuncReadRwRegX03;
|
||||
mbp->func_set[R_R_REG]=FuncReadRRegX04;
|
||||
mbp->func_set[W_RW_COIL]=FuncWriteRwCoilX05;
|
||||
mbp->func_set[W_RW_REG]=FuncWriteRwRegX06;
|
||||
mbp->func_set[W_MRW_REG]=FuncWriteRwMregsX10;
|
||||
mbp->func_set[W_MRW_COIL]=FuncWriteRwMcoilsX0f;
|
||||
mbp->func_set[REPORT_SlAVE_ID]=FuncReportSlaveIDX11;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @description:初始化存储区
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:01:47
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
int MbMemoryInit(MBmemoryType*mbm)
|
||||
{
|
||||
mbm->rcoil_mem=(coils8_t*)malloc(sizeof(coils8_t)*RCOILMEM);
|
||||
mbm->rreg_mem=(reg_t*)malloc(sizeof(reg_t)*RREGMEM);
|
||||
mbm->rwcoil_mem=(coils8_t*)malloc(sizeof(coils8_t)*RWCOILMEM);
|
||||
mbm->rwreg_mem=(reg_t*)malloc(sizeof(reg_t)*RWREGMEM);
|
||||
|
||||
memset(mbm->rwreg_mem,0,RWREGMEM);
|
||||
memset(mbm->rreg_mem,0,RREGMEM);
|
||||
memset(mbm->rcoil_mem,0,RCOILMEM);
|
||||
memset(mbm->rwcoil_mem,0,RWCOILMEM);
|
||||
|
||||
// mbm->rwreg_mem[0]=3;
|
||||
// mbm->rwreg_mem[1]=0x30ff;
|
||||
mbm->rwcoil_mem[0]=1;mbm->rwcoil_mem[2]=1;mbm->rwcoil_mem[4]=1;
|
||||
|
||||
if(mbm->rcoil_mem==NULL||mbm->rreg_mem==NULL||mbm->rwcoil_mem==NULL||mbm->rwreg_mem==NULL)
|
||||
{
|
||||
lw_error("memory is not full\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 释放存储区
|
||||
* @return {void}
|
||||
* @Date: 2023-07-25 17:02:22
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
void MbMemoryFree(MBmemoryType*mbm)
|
||||
{
|
||||
free(mbm->rcoil_mem);
|
||||
free(mbm->rreg_mem);
|
||||
free(mbm->rwcoil_mem);
|
||||
free(mbm->rwreg_mem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 创建tcp通信套接字
|
||||
* @param {int} port
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:02:39
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
int CreateSocket(int port)
|
||||
{
|
||||
int fd = -1, clientfd;
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(fd==-1)return -1;
|
||||
int recv_len;
|
||||
char *recv_buf;
|
||||
struct sockaddr_in tcp_addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
tcp_addr.sin_family = AF_INET;
|
||||
tcp_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
tcp_addr.sin_port = htons(port);
|
||||
memset(&(tcp_addr.sin_zero), 0, sizeof(tcp_addr.sin_zero));
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&tcp_addr, sizeof(struct sockaddr)) == -1) {
|
||||
lw_error("Unable to bind\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lw_print("tcp bind success, start to receive.\n");
|
||||
lw_notice("\nLocal Port:%d\n", port);
|
||||
|
||||
// setup socket fd as listening mode
|
||||
if (listen(fd,128) != 0 ) {
|
||||
lw_error("Unable to listen\n");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
lw_print("Tcp start to listen.\n");
|
||||
return fd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 读取请求报文的MBAP头部分
|
||||
* @param {int} fd {MbapType*}mbap
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:03:04
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
int ReadMbtcpMBAP(int fd,MbapType*mbap)
|
||||
{
|
||||
char buf[MODBUS_MBAP];
|
||||
read(fd,buf,MODBUS_MBAP);
|
||||
mbap->tid=(((u16_t)buf[0])<<8)+(u16_t)buf[1];//高位左移8位再加低位
|
||||
mbap->pid=(((u16_t)buf[2])<<8)+(u16_t)buf[3];
|
||||
mbap->len=(((u16_t)buf[4])<<8)+(u16_t)buf[5];
|
||||
mbap->uid=((u8_t)buf[6]);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 读取请求报文的PDU部分
|
||||
* @param {int} fd {PduType*}pdu
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:03:04
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
int ReadMbtcpPDU(int fd,PduType*pdu)
|
||||
{
|
||||
char buf[MODBUS_PDUHEAD];
|
||||
|
||||
int n=read(fd,buf,MODBUS_PDUHEAD);
|
||||
|
||||
|
||||
pdu->func=(u8_t)buf[0];//高位左移8位再加低位
|
||||
|
||||
if(n>3)
|
||||
{
|
||||
pdu->addr=(((u16_t)buf[1])<<8)+(u16_t)buf[2];
|
||||
pdu->operand1=(u8_t)buf[3];
|
||||
pdu->operand2=(u8_t)buf[4];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: 制作响应报文
|
||||
* @param {MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:11:23
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
void MakeResponse(MbapType*mbap,PduType*pdu,u8_t**resp,u16_t buf_len)
|
||||
{
|
||||
buf_len-=6;
|
||||
//这个长度实际是从数据长度位置到结束的长度,因此要将响应报文的总长减去事务头、协议、长度三个两字节数共6个
|
||||
(*resp)[0]=(u8_t)(mbap->tid>>8);(*resp)[1]=(u8_t)(0xff&mbap->tid);
|
||||
(*resp)[2]=(u8_t)(mbap->pid>>8);(*resp)[3]=(u8_t)(0xff&mbap->pid);
|
||||
(*resp)[4]=(u8_t)(buf_len>>8);(*resp)[5]=(u8_t)(0xff&buf_len);
|
||||
(*resp)[6]=mbap->uid;
|
||||
(*resp)[7]=pdu->func;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @description: 功能码0x1,负责读取从设备线圈的状态
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:12:00
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 17:10:31
|
||||
*/
|
||||
int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x01\n");
|
||||
printf("coils num:%d\n");
|
||||
u16_t coils_num=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;//线圈个数
|
||||
u16_t bytes_num=(coils_num/8+((coils_num%8)!=0));//输出的字节长度
|
||||
u16_t buf_len=Func0x_response_length[R_RW_COIL]+bytes_num;//response报文所占长度
|
||||
|
||||
*resp=(u8_t*)malloc(buf_len); memset(*resp,0,buf_len);
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
(*resp)[8]=(u8_t)bytes_num;
|
||||
u8_t*sub_mem=mem->rwcoil_mem;
|
||||
for(int i=0;i<coils_num;i++)
|
||||
{
|
||||
//按位将线圈值赋给response报文数据区,在内存区中,线圈按u8_t存放,但读取时要将其转换成位
|
||||
(*resp)[9+i/8]|=(sub_mem[i+pdu->addr]==1?((u8_t)1<<(i%8)):0);
|
||||
}
|
||||
|
||||
return buf_len;
|
||||
// u8_t
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0x2功能码,读离散输入状态
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:20:13
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x02\n");
|
||||
|
||||
u16_t coils_num=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;//线圈个数
|
||||
u16_t bytes_num=(coils_num/8+((coils_num%8)!=0));//输出的字节长度
|
||||
u16_t buf_len=Func0x_response_length[R_RW_COIL]+bytes_num;//response报文所占长度
|
||||
|
||||
*resp=(u8_t*)malloc(buf_len); memset(*resp,0,buf_len);
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
(*resp)[8]=(u8_t)bytes_num;
|
||||
u8_t*sub_mem=mem->rcoil_mem;
|
||||
for(int i=0;i<coils_num;i++)
|
||||
{
|
||||
//按位将线圈值赋给response报文数据区,在内存区中,线圈按u8_t存放,但读取时要将其转换成位
|
||||
(*resp)[9+i/8]|=(sub_mem[i+pdu->addr]==1?((u8_t)1<<(i%8)):0);
|
||||
}
|
||||
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 读保持寄存器
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:21:01
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x03\n");
|
||||
u16_t data_len=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;
|
||||
|
||||
u16_t buf_len=Func0x_response_length[R_RW_REG]+data_len*2;
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)data_len*2;
|
||||
|
||||
u16_t*sub_mem=mem->rwreg_mem;
|
||||
|
||||
u16_t addr_mem=pdu->addr,addr_resp=9;
|
||||
int c=0;
|
||||
while(c<data_len)
|
||||
{
|
||||
(*resp)[addr_resp]=(u8_t)(sub_mem[addr_mem]>>8);
|
||||
(*resp)[addr_resp+1]=(u8_t)(sub_mem[addr_mem]&0xff);
|
||||
addr_resp+=2;addr_mem++;
|
||||
c++;
|
||||
}
|
||||
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0x4功能码,读输入寄存器
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:21:22
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x04\n");
|
||||
u16_t data_len=((u16_t)pdu->operand1<<8)+(u16_t)pdu->operand2;
|
||||
|
||||
u16_t buf_len=Func0x_response_length[R_R_REG]+data_len*2;
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)data_len*2;
|
||||
|
||||
u16_t*sub_mem=mem->rreg_mem;
|
||||
|
||||
u16_t addr_mem=pdu->addr,addr_resp=9;
|
||||
|
||||
int c=0;
|
||||
while(c<data_len)
|
||||
{
|
||||
(*resp)[addr_resp]=(u8_t)(sub_mem[addr_mem]>>8);
|
||||
(*resp)[addr_resp+1]=(u8_t)(sub_mem[addr_mem]&0xff);
|
||||
addr_resp+=2;addr_mem++;
|
||||
c++;
|
||||
}
|
||||
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0x5功能码,写单个线圈
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:21:51
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x05\n");
|
||||
u16_t addr_coil=pdu->addr;
|
||||
u16_t operand=(((u16_t)pdu->operand1)<<8)+(u16_t)pdu->operand2;
|
||||
if(operand==0xff00||operand==0x0000)
|
||||
{
|
||||
mem->rwcoil_mem[addr_coil]=(operand==0xff00?1:0);
|
||||
}
|
||||
|
||||
u16_t buf_len=Func0x_response_length[W_RW_COIL];
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)((pdu->addr)>>8);
|
||||
(*resp)[9]=(u8_t)(pdu->addr&0xff);
|
||||
(*resp)[10]=(u8_t)(pdu->operand1);
|
||||
(*resp)[11]=(u8_t)(pdu->operand2);
|
||||
|
||||
printf("write data:%x\n",operand);
|
||||
|
||||
return buf_len;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0x6功能码,写单个保持寄存器
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:22:38
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x06\n");
|
||||
u16_t addr_reg=pdu->addr;
|
||||
u16_t reg_data=(u16_t)((pdu->operand1)<<8)+(u16_t)(pdu->operand2);
|
||||
mem->rwreg_mem[addr_reg]=reg_data;
|
||||
u16_t buf_len=Func0x_response_length[W_RW_REG];
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)((pdu->addr)>>8);
|
||||
(*resp)[9]=(u8_t)(pdu->addr&0xff);
|
||||
(*resp)[10]=(u8_t)(pdu->operand1);
|
||||
(*resp)[11]=(u8_t)(pdu->operand2);
|
||||
|
||||
printf("write data:%x\n",reg_data);
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0xf功能码,写多个线圈
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:23:16
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x0f\n");
|
||||
u16_t coils_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2);
|
||||
|
||||
u16_t res_num=coils_num/8+(coils_num%8!=0)+1;
|
||||
|
||||
u8_t*recv_buf=(u8_t*)malloc(sizeof(u8_t)*res_num);
|
||||
|
||||
int n=read(fd,(char*)recv_buf,res_num);
|
||||
|
||||
|
||||
u8_t*sub_mem=mem->rwcoil_mem;
|
||||
|
||||
for(int i=0;i<coils_num;i++)
|
||||
{
|
||||
sub_mem[pdu->addr+i]=((recv_buf[1+i/8]&(1<<(i%8)))==0?0:1);
|
||||
}
|
||||
|
||||
|
||||
u16_t buf_len=Func0x_response_length[W_MRW_COIL];
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)((pdu->addr)>>8);
|
||||
(*resp)[9]=(u8_t)(pdu->addr&0xff);
|
||||
(*resp)[10]=(u8_t)(pdu->operand1);
|
||||
(*resp)[11]=(u8_t)(pdu->operand2);
|
||||
|
||||
free(recv_buf);
|
||||
|
||||
|
||||
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 0x10功能码,写多个保持寄存器
|
||||
* @param {MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp}
|
||||
* @return {int}
|
||||
* @Date: 2023-07-25 17:23:56
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x10\n");
|
||||
u16_t data_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2);
|
||||
u16_t res_num=data_num*2+1;
|
||||
u8_t*recv_buf=(u8_t*)malloc(sizeof(u8_t)*res_num);
|
||||
|
||||
|
||||
int n=read(fd,(char*)recv_buf,res_num);
|
||||
|
||||
// printf("%x %x %x\n",recv_buf[0],recv_buf[1],recv_buf[2]);
|
||||
|
||||
u16_t*sub_mem=mem->rwreg_mem;
|
||||
|
||||
for(int i=0;i<data_num;i++)
|
||||
{
|
||||
sub_mem[pdu->addr+i]=(((u16_t)(recv_buf[1+i*2]))<<8)+(u16_t)(recv_buf[1+i*2+1]);
|
||||
}
|
||||
|
||||
|
||||
u16_t buf_len=Func0x_response_length[W_MRW_REG];
|
||||
*resp=(u8_t*)malloc(buf_len);
|
||||
|
||||
MakeResponse(mbap,pdu,resp,buf_len);
|
||||
|
||||
(*resp)[8]=(u8_t)((pdu->addr)>>8);
|
||||
(*resp)[9]=(u8_t)(pdu->addr&0xff);
|
||||
(*resp)[10]=(u8_t)(pdu->operand1);
|
||||
(*resp)[11]=(u8_t)(pdu->operand2);
|
||||
|
||||
|
||||
free(recv_buf);
|
||||
|
||||
return buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 报告从设备id
|
||||
* @param {int} fd
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:24:43
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp)
|
||||
{
|
||||
printf("enter x11\n");
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 发送响应报文
|
||||
* @param {int} fd
|
||||
* @param {u16_t} n
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:24:55
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int SendResponse(int fd,u8_t**buf,u16_t n)
|
||||
{
|
||||
printf("Response:");
|
||||
for(int i=0;i<n;i++)printf("%x ",(*buf)[i]);
|
||||
printf("\n\n");
|
||||
int num=write(fd,(char*)*buf,n);
|
||||
free(*buf);
|
||||
return num;
|
||||
};
|
||||
|
||||
/**
|
||||
* @Description: 读取键盘输入,并生成请求报文
|
||||
* @param {u8_t} flag
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:25:26
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
int GenerateModbusRequest(MbapType*mbap,PduType*pdu,u8_t flag,u8_t**request)
|
||||
{
|
||||
int send_buf_length=0;
|
||||
while(1)
|
||||
{
|
||||
printf("\nPlease set the region of command\n");
|
||||
|
||||
printf("The slave id:");
|
||||
scanf("%d",&mbap->uid);printf("%d",mbap->uid);printf("\n");
|
||||
|
||||
printf("Please input function code:");
|
||||
scanf("%x",&pdu->func);printf("%x",pdu->func);printf("\n");
|
||||
|
||||
printf("The address:");
|
||||
scanf("%d",&pdu->addr);printf("%d",pdu->addr);printf("\n");
|
||||
|
||||
switch (pdu->func)
|
||||
{
|
||||
case R_RW_COIL:
|
||||
case R_R_COIL:printf("The number of coils you want read:");break;
|
||||
case R_RW_REG:
|
||||
case R_R_REG:printf("The number of registers you want read:");break;
|
||||
|
||||
case W_RW_COIL:printf("The value of coil you want write(1 or 0):");break;
|
||||
case W_RW_REG:printf("The value of register you want write:");break;
|
||||
|
||||
case W_MRW_COIL:printf("The number of coils you want write:");break;
|
||||
case W_MRW_REG:printf("The number of registers you want write:");break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
u16_t num;
|
||||
scanf("%d",&num);printf("%d\n",num);
|
||||
if(pdu->func==W_RW_COIL)
|
||||
{
|
||||
pdu->operand2=0;
|
||||
pdu->operand1=(num==1?0xff:0);
|
||||
}
|
||||
else {
|
||||
pdu->operand1=(u8_t)(num>>8);
|
||||
pdu->operand2=(u8_t)(num&0x00ff);
|
||||
}
|
||||
|
||||
|
||||
if(pdu->func==W_MRW_REG)
|
||||
{
|
||||
send_buf_length=num*2+1+12;
|
||||
*request=(u8_t*)malloc(send_buf_length);
|
||||
memset(*request,0,send_buf_length);
|
||||
printf("input register data(decimal integer,in total %d):",num);
|
||||
(*request)[12]=(u8_t)(num*2);
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
u16_t tem;
|
||||
scanf("%d",&tem);printf("%d ",tem);
|
||||
(*request)[i*2+13]=(u8_t)(tem>>8);
|
||||
(*request)[i*2+13+1]=(u8_t)(tem&0x00ff);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else if(pdu->func==W_MRW_COIL)
|
||||
{
|
||||
send_buf_length=num/8+(num%8!=0)+1+12;
|
||||
*request=(u8_t*)malloc(send_buf_length);
|
||||
memset(*request,0,send_buf_length);
|
||||
printf("input coil data(0 or 1,in total %d):",num);
|
||||
(*request)[12]=(u8_t)(num/8+(num%8!=0));
|
||||
for(int i=0;i<num;i++)
|
||||
{
|
||||
u16_t tem;
|
||||
scanf("%d",&tem);printf("%d ",tem);
|
||||
if(tem==1)
|
||||
{
|
||||
(*request)[i/8+13]|=(1<<(i%8));
|
||||
// (*resp)[9+i/8]|=(sub_mem[i+pdu->addr]==1?((u8_t)1<<(i%8)):0);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
send_buf_length=12;
|
||||
*request=(u8_t*)malloc(send_buf_length);
|
||||
if((*request)==NULL)printf("erro\n");
|
||||
|
||||
}
|
||||
|
||||
(*request)[0]=(u8_t)(mbap->tid>>8);(*request)[1]=(u8_t)(0xff&mbap->tid);
|
||||
(*request)[2]=(u8_t)(mbap->pid>>8);(*request)[3]=(u8_t)(0xff&mbap->pid);
|
||||
(*request)[4]=(u8_t)((send_buf_length-6)>>8);(*request)[5]=(u8_t)(0xff&(send_buf_length-6));
|
||||
(*request)[6]=mbap->uid;
|
||||
(*request)[7]=pdu->func;
|
||||
(*request)[8]=(u8_t)(pdu->addr>>8);(*request)[9]=(u8_t)(0xff&pdu->addr);
|
||||
(*request)[10]=pdu->operand1;(*request)[11]=pdu->operand2;
|
||||
|
||||
printf("messege is:");
|
||||
for(int i=0;i<send_buf_length;i++)printf("%x ",(*request)[i]);
|
||||
printf("\n");
|
||||
|
||||
|
||||
printf("Decide to send? input 's' to send,else to reset the command:");
|
||||
char c;
|
||||
scanf("%c",&c);printf("%c\n",c);
|
||||
if(c=='s')break;
|
||||
else {
|
||||
free(*request);
|
||||
continue;
|
||||
};
|
||||
}
|
||||
|
||||
return send_buf_length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @Description: 发送请求报文
|
||||
* @param {int fd,u8_t**request,int n}
|
||||
* @return {}
|
||||
* @Date: 2023-07-25 17:26:10
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
void SendModbus(int fd,u8_t**request,int n)
|
||||
{
|
||||
n=write(fd,(char*)*request,n);
|
||||
free(*request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 读取请求报文
|
||||
* @param {(int fd,MbapType*mbap,PduType*pdu}
|
||||
* @return {void}
|
||||
* @Date: 2023-07-25 17:26:49
|
||||
* @Author: pgh_dd 1041315949@qq.com
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
*/
|
||||
void GetRequest(int fd,MbapType*mbap,PduType*pdu)
|
||||
{
|
||||
u16_t data_num;
|
||||
ReadMbtcpMBAP(fd,mbap);//先读取定长的MBAP部分
|
||||
|
||||
|
||||
read(fd,(char*)&pdu->func,1);//读取功能码
|
||||
|
||||
u8_t byte_num=0;
|
||||
u8_t *recv_buf;
|
||||
switch (pdu->func)
|
||||
{
|
||||
case R_R_COIL:
|
||||
case R_R_REG:
|
||||
case R_RW_COIL:
|
||||
case R_RW_REG:
|
||||
data_num=(((u16_t)(pdu->operand1))<<8)+(u16_t)(pdu->operand2);
|
||||
read(fd,&byte_num,1);
|
||||
recv_buf=(u8_t*)malloc(byte_num);
|
||||
read(fd,recv_buf,byte_num);
|
||||
/* code */
|
||||
break;
|
||||
case W_RW_COIL:
|
||||
case W_RW_REG:
|
||||
case W_MRW_REG:
|
||||
case W_MRW_COIL:
|
||||
recv_buf=(u8_t*)malloc(4);
|
||||
read(fd, recv_buf,4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Response: TID:%x func code:%x byte num:%x\n",mbap->tid,pdu->func,byte_num);
|
||||
|
||||
if(pdu->func==R_R_COIL||pdu->func==R_RW_COIL)
|
||||
{
|
||||
printf("coils:");
|
||||
for(int i=0;i<data_num;i++)
|
||||
{
|
||||
printf("%d ",(recv_buf[i/8]&(1<<(i%8)))==0?0:1);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else if(pdu->func==R_R_REG||pdu->func==R_RW_REG)
|
||||
{
|
||||
printf("registers:");
|
||||
// for(int i=0;i<byte_num;i++)printf("%x ",recv_buf[i]);printf("\n");
|
||||
for(int i=0;i<data_num;i++)
|
||||
{
|
||||
printf("%d ",(((u16_t)(recv_buf[i*2]))<<8)+(u16_t)(recv_buf[i*2+1]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
free(recv_buf);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @Description: 包含modbusTCP请求报文的包装解析,以及报文收发,和每种功能码对应操作的定义。
|
||||
* @Version: V1.0.0
|
||||
* @Author: 快乐小组
|
||||
* @Date: 2023-05-24 03:59:45
|
||||
* @LastEditors: pgh_dd 1041315949@qq.com
|
||||
* @LastEditTime: 2023-07-25 16:53:39
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MODBUSTCP_H__
|
||||
#define __MODBUSTCP_H__
|
||||
|
||||
#include<stdlib.h>
|
||||
#include<stdio.h>
|
||||
#include<transform.h>
|
||||
#include <sys_arch.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#define PORT 8888
|
||||
#define RCOILMEM 1000
|
||||
#define RREGMEM 1000
|
||||
#define RWCOILMEM 1000
|
||||
#define RWREGMEM 1000
|
||||
|
||||
#define MBTCP 1
|
||||
#define MBRTU 2
|
||||
//功能码
|
||||
#define R_RW_COIL 0x01
|
||||
#define R_R_COIL 0x02
|
||||
#define R_RW_REG 0x03
|
||||
#define R_R_REG 0x04
|
||||
#define W_RW_COIL 0x05
|
||||
#define W_RW_REG 0x06
|
||||
#define DIAGNOSTIC 0x08
|
||||
#define GET_COUNTER 0x0B
|
||||
#define W_MRW_COIL 0x0F
|
||||
#define W_MRW_REG 0x10
|
||||
#define REPORT_SlAVE_ID 0x11
|
||||
|
||||
|
||||
typedef u8_t coils8_t;
|
||||
typedef u16_t reg_t;
|
||||
|
||||
#define MODBUS_MBAP 7
|
||||
#define MODBUS_PDUHEAD 5
|
||||
|
||||
|
||||
//定义存储区结构体
|
||||
typedef struct MbMemory
|
||||
{
|
||||
coils8_t*rcoil_mem;
|
||||
reg_t*rreg_mem;
|
||||
coils8_t*rwcoil_mem;
|
||||
reg_t*rwreg_mem;
|
||||
}MBmemoryType;
|
||||
//初始化存储区的函数
|
||||
int MbMemoryInit(MBmemoryType*mb);
|
||||
//释放存储区
|
||||
void MbMemoryFree(MBmemoryType*mb);
|
||||
|
||||
|
||||
//协议的固定部分为12个字节,当功能码为写多个数据时,后续还有不定长的数据部分
|
||||
typedef struct mbap
|
||||
{
|
||||
//MbapType
|
||||
u16_t tid;
|
||||
u16_t pid;
|
||||
u16_t len;
|
||||
u8_t uid;
|
||||
|
||||
/* data */
|
||||
}MbapType;
|
||||
|
||||
typedef struct pdu
|
||||
{
|
||||
u8_t func;
|
||||
|
||||
u16_t addr;
|
||||
|
||||
u8_t operand1;
|
||||
u8_t operand2;
|
||||
/* data */
|
||||
}PduType;
|
||||
|
||||
int CreateSocket(int port);
|
||||
|
||||
int ReadMbtcpMBAP(int fd,MbapType*mb_s);
|
||||
int ReadMbtcpPDU(int fd,PduType*mb_s);
|
||||
|
||||
|
||||
//操作函数
|
||||
|
||||
int FuncReadRwCoilX01(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRCoilX02(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRwRegX03(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncReadRRegX04(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwCoilX05(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwRegX06(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwMcoilsX0f(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
int FuncWriteRwMregsX10(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
|
||||
int FuncReportSlaveIDX11(MBmemoryType*mem,int fd,MbapType*mbap,PduType*pdu,u8_t**resp);
|
||||
//位地址转换字节地址
|
||||
|
||||
//定义解析器结构体
|
||||
typedef struct mbparser
|
||||
{
|
||||
int (*func_set[20])(MBmemoryType*,int,MbapType*,PduType*,u8_t**resp);
|
||||
}MbParserType;
|
||||
//解析器初始化,实际上就是每个功能码对应的操作函数的注册
|
||||
void MbparserInit(MbParserType*mbp,u8_t flag);
|
||||
|
||||
void MakeResponse(MbapType*,PduType*,u8_t**,u16_t);
|
||||
|
||||
int SendResponse(int fd,u8_t**buf,u16_t n);
|
||||
|
||||
|
||||
// void func(PDU*pdu);
|
||||
|
||||
// void delete_modbus_request();
|
||||
//主机程序
|
||||
int GenerateModbusRequest(MbapType*,PduType*,u8_t flag,u8_t**request);
|
||||
|
||||
void SendModbus(int fd,u8_t**request,int n);
|
||||
|
||||
void GetRequest(int fd,MbapType*,PduType*);
|
||||
#endif
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (c) 2022 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file lwip_tcp_socket_demo.c
|
||||
* @brief TCP socket demo based on LwIP
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-03-21
|
||||
*/
|
||||
|
||||
#include <transform.h>
|
||||
#include"modbus_tcp.h"
|
||||
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
#include <sys_arch.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include "lwip/sys.h"
|
||||
#endif
|
||||
|
||||
#ifdef ADD_NUTTX_FEATURES
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "stdio.h"
|
||||
#endif
|
||||
|
||||
#define TCP_DEMO_BUF_SIZE 65535
|
||||
#define TCP_DEMO_SEND_TIMES 20
|
||||
#define LWIP_TCP_DEMO_TASK_STACK_SIZE 4096
|
||||
#define LWIP_TCP_DEMO_TASK_PRIO 20
|
||||
|
||||
static pthread_t tcp_client_task;
|
||||
static pthread_t tcp_server_task;
|
||||
|
||||
static char tcp_demo_ipaddr[] = {192, 168, 31, 77};
|
||||
static char tcp_demo_netmask[] = {255, 255, 255, 0};
|
||||
static char tcp_demo_gwaddr[] = {192, 168, 31, 1};
|
||||
|
||||
#ifdef ADD_NUTTX_FEATURES
|
||||
#define lw_print printf
|
||||
#define lw_notice printf
|
||||
#define lw_error printf
|
||||
|
||||
#define LWIP_DEMO_TIMES 3
|
||||
#define LWIP_TARGET_PORT 4840
|
||||
#endif
|
||||
|
||||
static uint16_t tcp_socket_port = 8888;
|
||||
static char tcp_ip_str[128] = {0};
|
||||
|
||||
/******************************************************************************/
|
||||
static void TcpSocketConfigParam(char *ip_str)
|
||||
{
|
||||
int ip1, ip2, ip3, ip4, port = 0;
|
||||
|
||||
if(ip_str == NULL)
|
||||
return;
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port)) {
|
||||
printf("config ip %s port %d\n", ip_str, port);
|
||||
strcpy(tcp_ip_str, ip_str);
|
||||
if(port)
|
||||
tcp_socket_port = port;
|
||||
return;
|
||||
}
|
||||
|
||||
if(sscanf(ip_str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4)) {
|
||||
printf("config ip %s\n", ip_str);
|
||||
strcpy(tcp_ip_str, ip_str);
|
||||
}
|
||||
}
|
||||
|
||||
static void *ModbusTcpServer(void *arg)
|
||||
{
|
||||
|
||||
u8_t uid=1;//定义从设备id和存储区
|
||||
|
||||
MBmemoryType mbm;//定义存储区
|
||||
if(MbMemoryInit(&mbm)==-1)//初始化存储区,包括对四个存储区进行内存分配
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
|
||||
MbParserType mb_parser;//初始化功能码解析器
|
||||
MbparserInit(&mb_parser,MBTCP);//初始化解析器,将功能码对应函数注册
|
||||
|
||||
int fd=CreateSocket(PORT);//创建监听套接字
|
||||
if(fd==-1)return 0;
|
||||
|
||||
int recv_len;
|
||||
char *recv_buf;
|
||||
struct sockaddr_in tcp_addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
while(1)
|
||||
{
|
||||
struct sockaddr_in tcp_addr;
|
||||
socklen_t addr_len;
|
||||
|
||||
printf("wait accept\n");
|
||||
int clientfd = accept(fd, (struct sockaddr *)&tcp_addr, (socklen_t*)&addr_len);
|
||||
|
||||
if(clientfd==-1)
|
||||
{
|
||||
lw_error("Unable to listen\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
MbapType mbap;
|
||||
PduType pdu;
|
||||
ReadMbtcpMBAP(clientfd,&mbap);//读取数据前7字节为mbap初始化
|
||||
|
||||
if(mbap.uid!=uid){//检验是否为此从机
|
||||
close(clientfd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ReadMbtcpPDU(clientfd,&pdu);//读取pdu和一些定长部分
|
||||
|
||||
printf("OP:%x\n",pdu.func);
|
||||
printf("ADDR:%x\n",pdu.addr);
|
||||
|
||||
u8_t* response_buf;//定义操作返回的指针
|
||||
u8_t buf_len=mb_parser.func_set[pdu.func](&mbm,clientfd,&mbap,&pdu,&response_buf);
|
||||
|
||||
SendResponse(clientfd,&response_buf,buf_len);
|
||||
// return NULL;
|
||||
//执行操作
|
||||
|
||||
}
|
||||
close(clientfd);
|
||||
}
|
||||
close(fd);
|
||||
MbMemoryFree(&mbm);//释放存储区
|
||||
}
|
||||
|
||||
void TestModbusTcpServer(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_print("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
TcpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ADD_NUTTX_FEATURES
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
ModbusTcpServer(NULL);
|
||||
}
|
||||
|
||||
PRIV_SHELL_CMD_FUNCTION(TestModbusTcpServer, a modbusS test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
||||
static void *ModbusTcpClient(void *arg)
|
||||
{
|
||||
u16_t counter=0;
|
||||
int fd = -1;
|
||||
int ret;
|
||||
|
||||
// lw_print("2023-05-27 Peng Guanhua\n");
|
||||
lw_print("%s start\n", __func__);
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (fd < 0) {
|
||||
lw_print("Socket error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char tcp_ip_str[128]="192.168.31.148";
|
||||
u16_t tcp_socket_port=6000;
|
||||
|
||||
|
||||
printf("%s\n",tcp_ip_str);
|
||||
struct sockaddr_in tcp_sock;
|
||||
tcp_sock.sin_family = AF_INET;
|
||||
tcp_sock.sin_port = htons(tcp_socket_port);
|
||||
tcp_sock.sin_addr.s_addr = inet_addr(tcp_ip_str);
|
||||
printf("%s\n",tcp_ip_str);
|
||||
|
||||
memset(&(tcp_sock.sin_zero), 0, sizeof(tcp_sock.sin_zero));
|
||||
|
||||
ret = connect(fd, (struct sockaddr *)&tcp_sock, sizeof(struct sockaddr));
|
||||
|
||||
if (ret < 0) {
|
||||
lw_print("Unable to connect %s:%d = %d\n", tcp_ip_str, tcp_socket_port, ret);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lw_print("TCP connect %s:%d success, start.\n", tcp_ip_str, tcp_socket_port);
|
||||
|
||||
|
||||
while (1) {
|
||||
|
||||
MbapType mbap={counter,0,0,0};
|
||||
PduType pdu;
|
||||
u8_t*request;
|
||||
|
||||
int mesg_len=GenerateModbusRequest(&mbap,&pdu,MBTCP,&request);
|
||||
SendModbus(fd,&request,mesg_len);
|
||||
GetRequest(fd,&mbap,&pdu);
|
||||
counter++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TestModbusTcpClient(int argc, char *argv[])
|
||||
{
|
||||
if(argc >= 2) {
|
||||
lw_print("lw: [%s] target ip %s\n", __func__, argv[1]);
|
||||
TcpSocketConfigParam(argv[1]);
|
||||
}
|
||||
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
lwip_config_tcp(0, tcp_demo_ipaddr, tcp_demo_netmask, tcp_demo_gwaddr);
|
||||
|
||||
#endif
|
||||
#ifdef ADD_NUTTX_FEATURES
|
||||
pthread_attr_t attr = PTHREAD_ATTR_INITIALIZER;
|
||||
attr.priority = LWIP_TCP_DEMO_TASK_PRIO;
|
||||
attr.stacksize = LWIP_TCP_DEMO_TASK_STACK_SIZE;
|
||||
#endif
|
||||
|
||||
ModbusTcpClient(NULL);
|
||||
}
|
||||
PRIV_SHELL_CMD_FUNCTION(TestModbusTcpClient, a modbustcpC test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||
|
|
@ -9,13 +9,15 @@
|
|||
基数树节点设计为:
|
||||
|
||||
```c
|
||||
typedef struct _node {
|
||||
void* value;
|
||||
struct _node* next[NODE_SIZE];
|
||||
} node;
|
||||
typedef struct radix_node
|
||||
{
|
||||
void *value;
|
||||
struct radix_node *child[NODE_SIZE];
|
||||
struct radix_node *parent;
|
||||
} radix_node;
|
||||
```
|
||||
|
||||
其中,节点在树中的路径即为键,`value` 存储值,`NODE_SIZE` 定义为 128,足以容纳所有 ASCII 值。
|
||||
其中,节点在树中的路径即为键,为`unsigned int`类型,`value` 存储值,`NODE_SIZE` 定义为 4,即每个树节点包含2个bit位,可以根据实际需求调整。
|
||||
|
||||
一共实现了 5 个函数,分别为:
|
||||
|
||||
|
@ -32,20 +34,19 @@ typedef struct _node {
|
|||
测试程序定义了以下键值对:
|
||||
|
||||
```c
|
||||
char keys[][MAX_WORD_LEN] = {
|
||||
char values[][16] = {
|
||||
"what",
|
||||
"where",
|
||||
"why",
|
||||
"how",
|
||||
"hello!",
|
||||
"apple",
|
||||
"12345"
|
||||
};
|
||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
"12345"};
|
||||
unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
```
|
||||
|
||||
1. 程序的第一部分创建了基数树,并且将定义的 7 个键值对的前 6 个插入了基数树,然后分别查找 7 个键,前 6 个均可以找到对应的值,最后一个未插入,因此无法找到
|
||||
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||
2. 程序的第二部分从基数树中删除了 `where` 和 `how` 两个值的键,再次分别查找 7 个键,删除的键值对和未插入的键值对均无法找到
|
||||
3. 程序的第三部分重新插入了已删除的 `where` 和未插入过的 `12345` ,再次分别查找 7 个键,新插入的值可以检索到
|
||||
4. 程序的第四部分将基数树销毁,再次分别查找 7 个键,所有的键值对均无法找到
|
||||
|
||||
|
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 96 KiB |
|
@ -1,23 +1,27 @@
|
|||
/**
|
||||
* @file: test_radix_tree.c
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
* @file: test_radix_tree.c
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
|
||||
#include <transform.h>
|
||||
#include "test_radix_tree.h"
|
||||
|
||||
/**
|
||||
* @description: Create a radix tree node
|
||||
* @return node pointer
|
||||
*/
|
||||
node* CreateNode()
|
||||
radix_node *CreateNode()
|
||||
{
|
||||
node* n = (node*)malloc(sizeof(node));
|
||||
n->value = NULL;
|
||||
for (int i = 0; i < NODE_SIZE; i++) {
|
||||
n->next[i] = NULL;
|
||||
radix_node *n = (radix_node *)malloc(sizeof(radix_node));
|
||||
if (n != NULL)
|
||||
{
|
||||
n->parent = NULL;
|
||||
n->value = NULL;
|
||||
for (int i = 0; i < NODE_SIZE; ++i)
|
||||
{
|
||||
n->child[i] = NULL;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
@ -29,21 +33,32 @@ node* CreateNode()
|
|||
* @param value - new node value
|
||||
* @return void
|
||||
*/
|
||||
void InsertNode(node* root, const char* key, void* value)
|
||||
int InsertNode(radix_node *root, unsigned int key, void *value)
|
||||
{
|
||||
if (root == NULL) {
|
||||
return;
|
||||
if (root == NULL)
|
||||
{
|
||||
return -1; // The root node is empty
|
||||
}
|
||||
node* cur = root;
|
||||
size_t len = strlen(key);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t b = (uint8_t)key[i];
|
||||
if (cur->next[b] == NULL) {
|
||||
cur->next[b] = CreateNode();
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
if (!cur->child[temp])
|
||||
{
|
||||
cur->child[temp] = CreateNode();
|
||||
if (!cur->child[temp])
|
||||
return -2; // Failed to apply for a node
|
||||
cur->child[temp]->parent = cur;
|
||||
}
|
||||
cur = cur->next[b];
|
||||
cur = cur->child[temp];
|
||||
}
|
||||
if (cur->value == value)
|
||||
return -3; // Repeat insertion
|
||||
if (cur->value != NULL)
|
||||
return -4; // Already occupied
|
||||
cur->value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,38 +67,27 @@ void InsertNode(node* root, const char* key, void* value)
|
|||
* @param key - key which is needed to delete
|
||||
* @return void
|
||||
*/
|
||||
void DeleteNode(node* root, const char* key)
|
||||
void DeleteNode(radix_node *root, unsigned int key)
|
||||
{
|
||||
if (root == NULL) {
|
||||
if (root == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
node** cur = &root;
|
||||
size_t len = strlen(key);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t b = (uint8_t)key[i];
|
||||
if ((*cur)->next[b] == NULL) {
|
||||
return;
|
||||
}
|
||||
cur = &((*cur)->next[b]);
|
||||
}
|
||||
|
||||
if ((*cur)->value == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
(*cur)->value = NULL;
|
||||
|
||||
int has_children = 0;
|
||||
for (int i = 0; i < NODE_SIZE; i++) {
|
||||
if ((*cur)->next[i] != NULL) {
|
||||
has_children = 1;
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
cur = cur->child[temp];
|
||||
if (!cur)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_children) {
|
||||
free(*cur);
|
||||
(*cur) = NULL;
|
||||
}
|
||||
|
||||
if (!cur)
|
||||
return;
|
||||
|
||||
cur->parent->child[temp] = NULL;
|
||||
free(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,20 +96,23 @@ void DeleteNode(node* root, const char* key)
|
|||
* @param key - key which is needed to find
|
||||
* @return value pointer corresponding to key
|
||||
*/
|
||||
void* FindNode(node* root, const char* key)
|
||||
void *FindNode(radix_node *root, unsigned int key)
|
||||
{
|
||||
if (root == NULL) {
|
||||
if (root == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
node* cur = root;
|
||||
size_t len = strlen(key);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t b = (uint8_t)key[i];
|
||||
if (cur->next[b] == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cur = cur->next[b];
|
||||
radix_node *cur = root;
|
||||
int temp;
|
||||
for (int i = radix_tree_height - 1; i >= 0; --i)
|
||||
{
|
||||
temp = CHECK_BITS(key, i);
|
||||
cur = cur->child[temp];
|
||||
if (!cur)
|
||||
break;
|
||||
}
|
||||
if (!cur)
|
||||
return NULL;
|
||||
return cur->value;
|
||||
}
|
||||
|
||||
|
@ -114,73 +121,88 @@ void* FindNode(node* root, const char* key)
|
|||
* @param root - radix tree root
|
||||
* @return void
|
||||
*/
|
||||
void DestroyTree(node* root)
|
||||
void DestroyTree(radix_node *root)
|
||||
{
|
||||
if (root == NULL) {
|
||||
if (root == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < NODE_SIZE; i++) {
|
||||
DestroyTree(root->next[i]);
|
||||
for (int i = 0; i < NODE_SIZE; i++)
|
||||
{
|
||||
DestroyTree(root->child[i]);
|
||||
}
|
||||
free(root);
|
||||
}
|
||||
|
||||
void TestRadix()
|
||||
{
|
||||
char keys[][MAX_WORD_LEN] = {
|
||||
char values[][16] = {
|
||||
"what",
|
||||
"where",
|
||||
"why",
|
||||
"how",
|
||||
"hello!",
|
||||
"apple",
|
||||
"12345"
|
||||
};
|
||||
int values[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
"12345"};
|
||||
unsigned int keys[] = {1, 2, 3, 4, 5, 6, 7};
|
||||
|
||||
printf("\nCreate tree and add key & value:\n");
|
||||
node* root = CreateNode();
|
||||
if (!root) printf("Create node failed.\n");
|
||||
radix_node *root = CreateNode();
|
||||
if (!root)
|
||||
printf("Create node failed.\n");
|
||||
|
||||
int num = sizeof(keys) / sizeof(keys[0]);
|
||||
for (int i = 0; i < num - 1; ++i) {
|
||||
for (int i = 0; i < num - 1; ++i)
|
||||
{
|
||||
InsertNode(root, keys[i], &values[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
int* v = (int*)FindNode(root, keys[i]);
|
||||
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
|
||||
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x not found\n", i, keys[i]);
|
||||
}
|
||||
|
||||
printf("\nDelete \"where\" and \"how\":\n");
|
||||
DeleteNode(root, keys[1]);
|
||||
DeleteNode(root, keys[3]);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
int* v = (int*)FindNode(root, keys[i]);
|
||||
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
|
||||
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
|
||||
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x not found\n", i, keys[i]);
|
||||
}
|
||||
|
||||
printf("\nInsert \"where\" and \"12345\":\n");
|
||||
InsertNode(root, keys[1], &values[1]);
|
||||
InsertNode(root, keys[6], &values[6]);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
int* v = (int*)FindNode(root, keys[i]);
|
||||
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
|
||||
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x not found\n", i, keys[i]);
|
||||
}
|
||||
|
||||
printf("\nDestroy tree:\n");
|
||||
DestroyTree(root);
|
||||
root = NULL;
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
int* v = (int*)FindNode(root, keys[i]);
|
||||
if (v) printf("keys[%d] \"%s\"'v = %d, values[%d] = %d\n", i, keys[i], *v, i, values[i]);
|
||||
else printf("keys[%d] \"%s\" not found\n", i, keys[i]);
|
||||
for (int i = 0; i < num; ++i)
|
||||
{
|
||||
char *v = (char *)FindNode(root, keys[i]);
|
||||
if (v)
|
||||
printf("keys[%d] %x, values[%d] = %s\n", i, keys[i], i, v);
|
||||
else
|
||||
printf("keys[%d] %x not found\n", i, keys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
/**
|
||||
* @file: test_radix_tree.h
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
* @file: test_radix_tree.h
|
||||
* @brief: Implement a simple radix tree
|
||||
* @version: 1.0
|
||||
* @date: 2023/5/24
|
||||
*/
|
||||
|
||||
#define NODE_SIZE 128
|
||||
#define MAX_WORD_LEN 128
|
||||
#include <transform.h>
|
||||
|
||||
typedef struct _node {
|
||||
void* value;
|
||||
struct _node* next[NODE_SIZE];
|
||||
} node;
|
||||
#define NODE_SIZE 4
|
||||
#define BITS 2
|
||||
#define CHECK_BITS(key, pos) ((((unsigned int)(key)) << (sizeof(int) * 8 - (pos + 1) * BITS)) >> (sizeof(int) * 8 - BITS))
|
||||
|
||||
node* CreateNode();
|
||||
void InsertNode(node* root, const char* key, void* value);
|
||||
void DeleteNode(node* root, const char* key);
|
||||
void* FindNode(node* root, const char* key);
|
||||
void DestroyTree(node* root);
|
||||
const int radix_tree_height = sizeof(void *) * 8 / BITS; // Height of tree
|
||||
|
||||
typedef struct radix_node
|
||||
{
|
||||
void *value;
|
||||
struct radix_node *child[NODE_SIZE];
|
||||
struct radix_node *parent;
|
||||
} radix_node;
|
||||
|
||||
radix_node *CreateNode();
|
||||
int InsertNode(radix_node *root, unsigned int key, void *value);
|
||||
void DeleteNode(radix_node *root, unsigned int key);
|
||||
void *FindNode(radix_node *root, unsigned int key);
|
||||
void DestroyTree(radix_node *root);
|
|
@ -22,26 +22,94 @@
|
|||
#include <transform.h>
|
||||
#ifdef ADD_XIZI_FEATURES
|
||||
|
||||
#define BSP_485_DIR_PIN 24
|
||||
//edu-arm board dir pin PG01----no.67 in XiZi_IIoT/board/edu_arm32/third_party_driver/gpio/connect_gpio.c
|
||||
#define BSP_485_DIR_PIN 67
|
||||
|
||||
static int pin_fd;
|
||||
static int uart_fd;
|
||||
static char write_485_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
|
||||
static char read_485_data[8] = {0};
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Input
|
||||
* @return
|
||||
*/
|
||||
static void Set485Input(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = BSP_485_DIR_PIN;
|
||||
pin_stat.val = GPIO_LOW;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Set Uart 485 Output
|
||||
* @return
|
||||
*/
|
||||
static void Set485Output(void)
|
||||
{
|
||||
struct PinStat pin_stat;
|
||||
pin_stat.pin = BSP_485_DIR_PIN;
|
||||
pin_stat.val = GPIO_HIGH;
|
||||
PrivWrite(pin_fd, &pin_stat, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Serial Write
|
||||
* @param write_data - write data
|
||||
* @param length - length
|
||||
* @return
|
||||
*/
|
||||
void Rs485Write(uint8_t *write_data, int length)
|
||||
{
|
||||
Set485Output();
|
||||
PrivTaskDelay(20);
|
||||
|
||||
PrivWrite(uart_fd, write_data, length);
|
||||
|
||||
PrivTaskDelay(15);
|
||||
Set485Input();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Control Framework Serial Read
|
||||
* @param read_data - read data
|
||||
* @param length - length
|
||||
* @return read data size
|
||||
*/
|
||||
int Rs485Read(uint8_t *read_data, int length)
|
||||
{
|
||||
int data_size = 0;
|
||||
int data_recv_size = 0;
|
||||
|
||||
while (data_size < length) {
|
||||
data_recv_size = PrivRead(uart_fd, read_data + data_size, length - data_size);
|
||||
data_size += data_recv_size;
|
||||
}
|
||||
|
||||
//need to wait 30ms , make sure write cmd again and receive data successfully
|
||||
PrivTaskDelay(30);
|
||||
|
||||
return data_size;
|
||||
}
|
||||
|
||||
void Test485(void)
|
||||
{
|
||||
int pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
|
||||
if (pin_fd < 0)
|
||||
{
|
||||
int read_data_length = 0;
|
||||
pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
|
||||
if (pin_fd < 0) {
|
||||
printf("open pin fd error:%d\n", pin_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
int uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
|
||||
if (uart_fd < 0)
|
||||
{
|
||||
uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
|
||||
if (uart_fd < 0) {
|
||||
printf("open pin fd error:%d\n", uart_fd);
|
||||
return;
|
||||
}
|
||||
printf("uart and pin fopen success\n");
|
||||
|
||||
//config led pin in board
|
||||
//config dir pin in board
|
||||
struct PinParam pin_parameter;
|
||||
memset(&pin_parameter, 0, sizeof(struct PinParam));
|
||||
pin_parameter.cmd = GPIO_CONFIG_MODE;
|
||||
|
@ -68,36 +136,34 @@ void Test485(void)
|
|||
uart_cfg.serial_bit_order = BIT_ORDER_LSB;
|
||||
uart_cfg.serial_invert_mode = NRZ_NORMAL;
|
||||
uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
|
||||
uart_cfg.serial_timeout = 1000;
|
||||
uart_cfg.serial_timeout = -1;
|
||||
uart_cfg.is_ext_uart = 0;
|
||||
|
||||
ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
|
||||
ioctl_cfg.args = (void *)&uart_cfg;
|
||||
|
||||
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg))
|
||||
{
|
||||
if (0 != PrivIoctl(uart_fd, OPE_INT, &ioctl_cfg)) {
|
||||
printf("ioctl uart fd error %d\n", uart_fd);
|
||||
PrivClose(uart_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
struct PinStat pin_dir;
|
||||
pin_dir.pin = BSP_485_DIR_PIN;
|
||||
while (1)
|
||||
{
|
||||
pin_dir.val = GPIO_HIGH;
|
||||
PrivWrite(pin_fd,&pin_dir,0);
|
||||
PrivWrite(uart_fd,"Hello world!\n",sizeof("Hello world!\n"));
|
||||
PrivTaskDelay(100);
|
||||
Rs485Write(write_485_data, sizeof(write_485_data));
|
||||
|
||||
pin_dir.val = GPIO_LOW;
|
||||
PrivWrite(pin_fd,&pin_dir,0);
|
||||
char recv_buff[100];
|
||||
memset(recv_buff,0,sizeof(recv_buff));
|
||||
PrivRead(uart_fd,recv_buff,20);
|
||||
printf("%s",recv_buff);
|
||||
PrivTaskDelay(100);
|
||||
while(1) {
|
||||
printf("ready to read data\n");
|
||||
|
||||
read_data_length = Rs485Read(read_485_data, sizeof(read_485_data));
|
||||
printf("%s read data length %d\n", __func__, read_data_length);
|
||||
for (int i = 0; i < read_data_length; i ++) {
|
||||
printf("i %d read data 0x%x\n", i, read_485_data[i]);
|
||||
}
|
||||
Rs485Write(read_485_data, read_data_length);
|
||||
memset(read_485_data, 0, sizeof(read_485_data));
|
||||
|
||||
printf("read data done\n");
|
||||
}
|
||||
|
||||
PrivClose(pin_fd);
|
||||
PrivClose(uart_fd);
|
||||
return;
|
||||
|
|
|
@ -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));
|
|
@ -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
|
|
@ -15,7 +15,6 @@
|
|||
// #include <user_api.h>
|
||||
#include <transform.h>
|
||||
|
||||
|
||||
extern int FrameworkInit();
|
||||
extern void ApplicationOtaTaskInit(void);
|
||||
int main(void)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
SRC_DIR += WebNet_XiUOS
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -1 +1 @@
|
|||
Subproject commit 956eafa24bb65f5bb84d293ab35bf27084473edf
|
||||
Subproject commit 60a8a500b93b47876c6eaff600e4cf2b8bf7b283
|
|
@ -180,7 +180,7 @@ int SerialRead(uint8_t *read_data, int length)
|
|||
int data_recv_size = 0;
|
||||
|
||||
while (data_size < length) {
|
||||
data_recv_size = PrivRead(uart_fd, read_data + data_recv_size, length);
|
||||
data_recv_size = PrivRead(uart_fd, read_data + data_size, length - data_size);
|
||||
data_size += data_recv_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ int PrivTimerModify(timer_t timerid, int flags, const struct itimerspec *restric
|
|||
/*********************fs**************************/
|
||||
#ifdef FS_VFS
|
||||
/************************Driver Posix Transform***********************/
|
||||
int PrivOpen(const char *path, int flags)
|
||||
int PrivOpen(const char *path, int flags, ...)
|
||||
{
|
||||
return open(path, flags);
|
||||
}
|
||||
|
|
|
@ -427,7 +427,7 @@ uint32_t PrivGetTickTime();
|
|||
|
||||
/*********************driver*************************/
|
||||
|
||||
int PrivOpen(const char *path, int flags);
|
||||
int PrivOpen(const char *path, int flags, ...);
|
||||
int PrivRead(int fd, void *buf, size_t len);
|
||||
int PrivWrite(int fd, const void *buf, size_t len);
|
||||
int PrivClose(int fd);
|
||||
|
|
|
@ -40,7 +40,8 @@ struct mq_attr {
|
|||
long mq_curmsgs; /* number of messages currently queued */
|
||||
};
|
||||
|
||||
mqd_t mq_open(const char *name, int oflag, ...);
|
||||
// mqd_t mq_open(const char *name, int oflag, ...);
|
||||
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
|
||||
int mq_close(mqd_t mqdes);
|
||||
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
|
||||
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio);
|
||||
|
|
|
@ -21,12 +21,13 @@
|
|||
|
||||
#include "include/mqueue.h"
|
||||
|
||||
mqd_t mq_open(const char *name, int oflag, ...)
|
||||
mqd_t mq_open(const char* name, int oflag, mode_t mode, struct mq_attr* attr)
|
||||
{
|
||||
|
||||
mqd_t mq;
|
||||
|
||||
mq = UserMsgQueueCreate( DEFAULT_MQUEUE_SIZE, DEFAULT_MAX_MSG_SIZE);
|
||||
// Todo: config mq by mode
|
||||
mq = UserMsgQueueCreate(attr->mq_msgsize, attr->mq_maxmsg);
|
||||
if (mq < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -39,12 +40,12 @@ int mq_close(mqd_t mqdes)
|
|||
return UserMsgQueueDelete(mqdes);
|
||||
}
|
||||
|
||||
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio)
|
||||
ssize_t mq_receive(mqd_t mqdes, char* msg_ptr, size_t msg_len, unsigned* msg_prio)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
*msg_prio = 0;
|
||||
ret = UserMsgQueueRecv(mqdes, msg_ptr, (unsigned long)&msg_len, 0);
|
||||
ret = UserMsgQueueRecv(mqdes, (void*)msg_ptr, msg_len, WAITING_FOREVER);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit d21965b1cbcfa99b2d36acd029a37f3f2eba612e
|
||||
Subproject commit a94c007cb4ee726cc29b10626f8bbfc19c989b89
|
|
@ -1 +1 @@
|
|||
Subproject commit 2896d7234688de77992e7e1872a7e67a9456b420
|
||||
Subproject commit 254754bc7d06011cbec4655cd229c8ccfb95240b
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := cache.c isr.c mmu.c
|
||||
SRC_FILES := cache.c isr.c abstraction_mmu.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: abstraction_mmu.c
|
||||
* @brief: the general management of system mmu
|
||||
* @version: 3.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/4/27
|
||||
*
|
||||
*/
|
||||
|
||||
#include <abstraction_mmu.h>
|
||||
|
||||
AbstractionMmu abstraction_mmu;
|
||||
|
||||
volatile uint32_t global_L1_pte_table[4096];
|
||||
|
||||
/**
|
||||
* @description: write cmd to CP15 register
|
||||
* @param reg_type - CP15 register type
|
||||
* @param val - ops val pointer
|
||||
* @return
|
||||
*/
|
||||
static void MmuCp15Write(uint8_t reg_type, uint32_t *val)
|
||||
{
|
||||
uint32_t write_val = *val;
|
||||
switch (reg_type) {
|
||||
case AM_MMU_CP15_TTBCR:
|
||||
TTBCR_W(write_val);
|
||||
AM_ISB;
|
||||
case AM_MMU_CP15_TTBR0:
|
||||
TTBR0_W(write_val);
|
||||
AM_ISB;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: read CP15 register from mmu
|
||||
* @param reg_type - CP15 register type
|
||||
* @param val - ops val pointer
|
||||
* @return
|
||||
*/
|
||||
static void MmuCp15Read(uint8_t reg_type, uint32_t *val)
|
||||
{
|
||||
uint32_t read_val = 0;
|
||||
switch (reg_type) {
|
||||
case AM_MMU_CP15_TTBCR:
|
||||
TTBCR_R(read_val);
|
||||
case AM_MMU_CP15_TTBR0:
|
||||
TTBR0_R(read_val);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
*val = read_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: write or read CP15 register to set mmu
|
||||
* @param ops_type - CP15 write or read
|
||||
* @param reg_type - CP15 register type
|
||||
* @param val - ops val pointer
|
||||
* @return
|
||||
*/
|
||||
static void MmuRegOps(uint8_t ops_type, uint8_t reg_type, uint32_t *val)
|
||||
{
|
||||
switch (ops_type) {
|
||||
case AM_MMU_CP15_WRITE:
|
||||
MmuCp15Write(reg_type, val);
|
||||
case AM_MMU_CP15_READ:
|
||||
MmuCp15Read(reg_type, val);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: Init abstraction_mmu function
|
||||
* @param mmu - abstraction mmu pointer
|
||||
* @param ttb_base - ttb base pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int _AbstractionMmuInit(AbstractionMmu *mmu, uint32_t *ttb_base)
|
||||
{
|
||||
mmu_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: map L1 or L2 page table section
|
||||
* @param mmu - abstraction mmu pointer
|
||||
* @param section_size - section size
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int _AbstractionMmuSectionMap(AbstractionMmu *mmu, uint32_t section_size)
|
||||
{
|
||||
uint32_t vaddr_length = mmu->vaddr_end - mmu->vaddr_start + 1;
|
||||
|
||||
mmu_map_l1_range(mmu->paddr_start, mmu->vaddr_start, vaddr_length,
|
||||
mmu->mmu_memory_type, mmu->mmu_shareability, mmu->mmu_access);
|
||||
|
||||
mmu->mmu_status = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: unmap L1 or L2 page table section
|
||||
* @param mmu - abstraction mmu pointer
|
||||
* @param vaddr_start - virtual address start
|
||||
* @param vaddr_size - virtual address size
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int _AbstractionMmuSectionUnmap(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size)
|
||||
{
|
||||
uint32_t *l1_umap_ventry = mmu->ttb_vbase + (vaddr_start >> AM_MMU_L1_SECTION_SHIFT);
|
||||
uint32_t vaddr_end = vaddr_start + vaddr_size - 1;
|
||||
uint32_t umap_count = (vaddr_end >> AM_MMU_L1_SECTION_SHIFT) - (vaddr_start >> AM_MMU_L1_SECTION_SHIFT) + 1;
|
||||
|
||||
while (umap_count) {
|
||||
AM_DMB;
|
||||
*l1_umap_ventry = 0;
|
||||
AM_DSB;
|
||||
|
||||
umap_count--;
|
||||
l1_umap_ventry += (1 << AM_MMU_L1_SECTION_SHIFT);//1MB section
|
||||
}
|
||||
|
||||
AM_DSB;
|
||||
CLEARTLB(0);//clear TLB data and configure
|
||||
AM_DSB;
|
||||
AM_ISB;
|
||||
mmu->mmu_status = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: switch ttb base by re-write ttbr register
|
||||
* @param mmu - abstraction mmu pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int _AbstractionMmuTtbSwitch(AbstractionMmu *mmu)
|
||||
{
|
||||
uint32_t ttbr, ttbcr;
|
||||
MmuRegOps(AM_MMU_CP15_READ, AM_MMU_CP15_TTBCR, &ttbcr);
|
||||
|
||||
/* Set TTBR0 with inner/outer write back write allocate and not shareable, [4:3]=01, [1]=0, [6,0]=01 */
|
||||
ttbr = ((mmu->ttb_pbase & 0xFFFFC000UL) | 0x9UL);
|
||||
/* enable TTBR0 */
|
||||
ttbcr = 0;
|
||||
|
||||
AM_DSB;
|
||||
MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBR0, &ttbr);
|
||||
MmuRegOps(AM_MMU_CP15_WRITE, AM_MMU_CP15_TTBCR, &ttbcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: get physical address transformed from virtual address
|
||||
* @param mmu - abstraction mmu pointer
|
||||
* @param vaddr - virtual address pointer
|
||||
* @param paddr - physical address pointer
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
static int _AbstracktonMmuTransform(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr)
|
||||
{
|
||||
uint32_t virtualAddress = *vaddr;
|
||||
|
||||
if (mmu->mmu_status) {
|
||||
mmu_virtual_to_physical(virtualAddress, paddr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct AbstractionMmuDone mmu_done = {
|
||||
.AbstractionMmuInit = _AbstractionMmuInit,
|
||||
.AbstractionMmuSectionMap = _AbstractionMmuSectionMap,
|
||||
.AbstractionMmuSectionUnmap = _AbstractionMmuSectionUnmap,
|
||||
.AbstractionMmuTtbSwitch = _AbstractionMmuTtbSwitch,
|
||||
.AbstracktonMmuTransform = _AbstracktonMmuTransform,
|
||||
};
|
||||
|
||||
/**
|
||||
* @description: init abstraciton mmu info when system start
|
||||
* @return success : 0 error : -1
|
||||
*/
|
||||
int SysInitAbstractionMmu(void)
|
||||
{
|
||||
abstraction_mmu.mmu_done = &mmu_done;
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: mmu.h
|
||||
* @brief: the general management of system mmu
|
||||
* @version: 3.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/5/24
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <mmu.h>
|
||||
|
||||
#define ARCH_ARM
|
||||
#ifdef ARCH_ARM
|
||||
/* ARM System Registers */
|
||||
#define AM_DSB __asm__ volatile("dsb" ::: "memory")
|
||||
#define AM_DMB __asm__ volatile("dmb" ::: "memory")
|
||||
#define AM_ISB __asm__ volatile("isb" ::: "memory")
|
||||
#define AM_WFI __asm__ volatile("wfi" ::: "memory")
|
||||
#define AM_BARRIER __asm__ volatile("":::"memory")
|
||||
#define AM_WFE __asm__ volatile("wfe" ::: "memory")
|
||||
#define AM_SEV __asm__ volatile("sev" ::: "memory")
|
||||
|
||||
#define TTBR0_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 0" : "=r"(val))
|
||||
#define TTBR0_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 0" ::"r"(val))
|
||||
|
||||
#define TTBCR_R(val) __asm__ volatile("mrc p15, 0, %0, c2, c0, 2" : "=r"(val))
|
||||
#define TTBCR_W(val) __asm__ volatile("mcr p15, 0, %0, c2, c0, 2" ::"r"(val))
|
||||
|
||||
#define CLEARTLB(val) __asm__ volatile("mcr p15, 0, %0, c8, c7, 0" ::"r"(val))
|
||||
#endif
|
||||
|
||||
#define AM_MMU_L1_PAGE_TABLE_SIZE (4 * 4096)
|
||||
#define AM_MMU_L1_SECTION_SHIFT 20
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AM_MMU_CP15_WRITE = 0,
|
||||
AM_MMU_CP15_READ,
|
||||
}MmuCP15OpsType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AM_MMU_CP15_TTBCR = 0,
|
||||
AM_MMU_CP15_TTBR0,
|
||||
AM_MMU_CP15_CLEARTLB,
|
||||
}MmuCP15RegType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AM_StronglyOrdered = 0,
|
||||
AM_Device,
|
||||
AM_OuterInner_WB_WA,
|
||||
AM_OuterInner_WT,
|
||||
AM_Noncacheable,
|
||||
}MmuMemoryType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AM_Noaccess = 0,
|
||||
AM_Read_Write,
|
||||
AM_Read,
|
||||
}MmuAccess;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AM_Shareable = 1,
|
||||
AM_Nonshareable = 0
|
||||
}MmuShareability;
|
||||
|
||||
struct AbstractionMmuDone
|
||||
{
|
||||
int (*AbstractionMmuInit)(AbstractionMmu *mmu, uint32_t *ttb_base);
|
||||
int (*AbstractionMmuSectionMap)(AbstractionMmu *mmu, uint32_t section_size);
|
||||
int (*AbstractionMmuSectionUnmap)(AbstractionMmu *mmu, uint32_t vaddr_start, uint32_t vaddr_size);
|
||||
int (*AbstractionMmuTtbSwitch)(AbstractionMmu *mmu);
|
||||
int (*AbstracktonMmuTransform)(AbstractionMmu *mmu, uint32_t *vaddr, uint32_t *paddr);
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ttb_vbase;
|
||||
uint32_t ttb_pbase;
|
||||
|
||||
uint32_t vaddr_start;
|
||||
uint32_t vaddr_end;
|
||||
uint32_t paddr_start;
|
||||
uint32_t paddr_end;
|
||||
|
||||
uint32_t vpaddr_offset;
|
||||
|
||||
uint32_t pte_attr;
|
||||
uint32_t mmu_status;
|
||||
|
||||
MmuMemoryType mmu_memory_type;
|
||||
MmuAccess mmu_access;
|
||||
MmuShareability mmu_shareability;
|
||||
|
||||
struct AbstractionMmuDone *mmu_done;
|
||||
|
||||
int lock;
|
||||
int link_list;
|
||||
}AbstractionMmu;
|
|
@ -1,4 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: cache.c
|
||||
* @brief: the general management of system cache
|
||||
* @version: 3.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/4/27
|
||||
*
|
||||
*/
|
||||
|
||||
void InvalidInsCache()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: memory.c
|
||||
* @brief: the general management of system memory
|
||||
* @version: 3.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2023/4/27
|
||||
*
|
||||
*/
|
|
@ -91,7 +91,7 @@ InterruptVectors:
|
|||
.long IsrEntry
|
||||
.long IsrEntry
|
||||
.long IsrEntry
|
||||
.long IsrEntry
|
||||
.long IRQ030_Handler
|
||||
.long IsrEntry
|
||||
.long IsrEntry
|
||||
.long IsrEntry
|
||||
|
|
|
@ -188,7 +188,7 @@ sudo apt install gdb-multiarch
|
|||
qemu-system-arm -machine lm3s6965evb -nographic -kernel build/XiZi-cortex-m3-emulator.elf -s -S
|
||||
```
|
||||
|
||||
然后要重新开启另一个linux系统终端一个终端,执行`riscv-none-embed-gdb`命令
|
||||
然后要重新开启另一个linux系统终端一个终端,执行命令
|
||||
|
||||
```
|
||||
gdb-multiarch build/XiZi-cortex-m3-emulator.elf -ex "target remote localhost:1234"
|
||||
|
|
|
@ -91,8 +91,8 @@ git clone https://gitlink.org.cn/xuos/xiuos.git
|
|||
|
||||
使用VScode打开代码,具体操作步骤为:在源码文件夹下打开系统终端,输入`code .`即可打开VScode开发环境,如下图所示:
|
||||
|
||||
<div align= "center">
|
||||
<img src = img/vscode.jpg width =1000>
|
||||
<div align= "center">
|
||||
<img src="img/vscode.jpg" width =1000>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -145,14 +145,14 @@ make BOARD=cortex-m4-emulator menuconfig
|
|||
|
||||
2.在menuconfig界面配置需要关闭和开启的功能,按回车键进入下级菜单,按Y键选中需要开启的功能,按N键选中需要关闭的功能,配置结束后保存并退出(本例旨在演示简单的输出例程,所以没有需要配置的选项,双击快捷键ESC退出配置)
|
||||
|
||||
<div align= "center">
|
||||
<img src = img/menuconfig.png width =1000>
|
||||
<div align= "center">
|
||||
<img src="img/menuconfig.png" width =1000>
|
||||
</div>
|
||||
|
||||
退出时选择`yes`保存上面所配置的内容,如下图所示:
|
||||
|
||||
<div align= "center">
|
||||
<img src = img/menuconfig1.png width =1000>
|
||||
<div align= "center">
|
||||
<img src="img/menuconfig1.png" width =1000>
|
||||
</div>
|
||||
|
||||
3.继续执行以下命令,进行编译
|
||||
|
@ -183,8 +183,8 @@ qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4-
|
|||
|
||||
QEMU运行起来后将会在终端上看到信息打印输出
|
||||
|
||||
<div align= "center">
|
||||
<img src = img/terminal.png width =1000>
|
||||
<div align= "center">
|
||||
<img src="img/terminal.png" width =1000>
|
||||
</div>
|
||||
|
||||
### 4.3 调试
|
||||
|
@ -204,5 +204,5 @@ qemu-system-arm -machine netduinoplus2 -nographic -kernel build/XiZi-cortex-m4-
|
|||
然后要重新开启另一个linux系统终端一个终端,执行`riscv-none-embed-gdb`命令
|
||||
|
||||
```
|
||||
gdb-multiarch build/XiZi-cortex-m4-emulator.elf -ex "target remote localhost:1234"
|
||||
gdb-multiarch build/XiZi-cortex-m4-emulator.elf -ex "target remote localhost:1234"
|
||||
```
|
|
@ -1,9 +1,11 @@
|
|||
export CROSS_COMPILE ?=/usr/bin/arm-none-eabi-
|
||||
|
||||
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
||||
export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
||||
# export CFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -fgnu89-inline -Wa,-mimplicit-it=thumb -Werror
|
||||
export AFLAGS := -c -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -x assembler-with-cpp -Wa,-mimplicit-it=thumb -gdwarf-2
|
||||
export LFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Wl,--gc-sections,-Map=XiZi-edu-arm32.map,-cref,-u,Reset_Handler -T $(BSP_ROOT)/link.lds
|
||||
export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror
|
||||
export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -Werror
|
||||
# export CXXFLAGS := -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -ffunction-sections -fdata-sections -Dgcc -O0 -gdwarf-2 -g -Werror
|
||||
|
||||
export APPLFLAGS :=
|
||||
|
||||
|
|
|
@ -1,74 +1,13 @@
|
|||
menuconfig BSP_USING_ADC1
|
||||
bool "Enable ADC1"
|
||||
default y
|
||||
if BSP_USING_ADC1
|
||||
config ADC1_BUS_NAME
|
||||
string "adc 1 bus name"
|
||||
default "adc1"
|
||||
if BSP_USING_ADC
|
||||
config ADC1_BUS_NAME
|
||||
string "adc 1 bus name"
|
||||
default "adc1"
|
||||
|
||||
config ADC1_DRIVER_NAME
|
||||
string "adc 1 driver name"
|
||||
default "adc1_drv"
|
||||
config ADC1_DRIVER_NAME
|
||||
string "adc 1 driver name"
|
||||
default "adc1_drv"
|
||||
|
||||
config ADC1_DEVICE_NAME
|
||||
string "adc 1 bus device name"
|
||||
default "adc1_dev"
|
||||
|
||||
config ADC1_GPIO_NUM
|
||||
int "adc 1 gpio pin num"
|
||||
default "0"
|
||||
|
||||
config ADC1_GPIO_DEF
|
||||
string "adc 1 gpio define type"
|
||||
default "A"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_ADC2
|
||||
bool "Enable ADC2"
|
||||
default y
|
||||
if BSP_USING_ADC2
|
||||
config ADC2_BUS_NAME
|
||||
string "adc 2 bus name"
|
||||
default "adc2"
|
||||
|
||||
config ADC2_DRIVER_NAME
|
||||
string "adc 2 driver name"
|
||||
default "adc2_drv"
|
||||
|
||||
config ADC2_DEVICE_NAME
|
||||
string "adc 2 bus device name"
|
||||
default "adc2_dev"
|
||||
|
||||
config ADC2_GPIO_NUM
|
||||
int "adc 2 gpio pin num"
|
||||
default "6"
|
||||
|
||||
config ADC2_GPIO_DEF
|
||||
string "adc 2 gpio define type"
|
||||
default "A"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_ADC3
|
||||
bool "Enable ADC3"
|
||||
default y
|
||||
if BSP_USING_ADC3
|
||||
config ADC3_BUS_NAME
|
||||
string "adc 3 bus name"
|
||||
default "adc3"
|
||||
|
||||
config ADC3_DRIVER_NAME
|
||||
string "adc 3 driver name"
|
||||
default "adc3_drv"
|
||||
|
||||
config ADC3_DEVICE_NAME
|
||||
string "adc 3 bus device name"
|
||||
default "adc3_dev"
|
||||
|
||||
config ADC3_GPIO_NUM
|
||||
int "adc 3 gpio pin num"
|
||||
default "0"
|
||||
|
||||
config ADC3_GPIO_DEF
|
||||
string "adc 3 gpio define type"
|
||||
default "A"
|
||||
endif
|
||||
config ADC1_DEVICE_NAME
|
||||
string "adc 1 bus device name"
|
||||
default "adc1_dev"
|
||||
endif
|
||||
|
|
|
@ -20,79 +20,251 @@
|
|||
|
||||
#include <connect_adc.h>
|
||||
|
||||
#define _ADC_CONS(string1, string2) string1##string2
|
||||
#define ADC_CONS(string1, string2) _ADC_CONS(string1, string2)
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef BSP_USING_ADC1
|
||||
#define ADC1_GPIO ADC_CONS(GPIO_Pin_, ADC1_GPIO_NUM)
|
||||
/* The clock source of ADC. */
|
||||
#define ADC_CLK_SYS_CLK (1U)
|
||||
#define ADC_CLK_PLLH (2U)
|
||||
#define ADC_CLK_PLLA (3U)
|
||||
|
||||
/*
|
||||
* Selects a clock source according to the application requirements.
|
||||
* PCLK4 is the clock for digital interface.
|
||||
* PCLK2 is the clock for analog circuit.
|
||||
* PCLK4 and PCLK2 are synchronous when the clock source is PLL.
|
||||
* PCLK4 : PCLK2 = 1:1, 2:1, 4:1, 8:1, 1:2, 1:4.
|
||||
* PCLK2 is in range [1MHz, 60MHz].
|
||||
* If the system clock is selected as the ADC clock, macro 'ADC_ADC_CLK' can only be defined as 'CLK_PERIPHCLK_PCLK'.
|
||||
* If PLLH is selected as the ADC clock, macro 'ADC_ADC_CLK' can be defined as 'CLK_PERIPHCLK_PLLx'(x=Q, R).
|
||||
* If PLLA is selected as the ADC clock, macro 'ADC_ADC_CLK' can be defined as 'CLK_PERIPHCLK_PLLXx'(x=P, Q, R).
|
||||
*/
|
||||
#define ADC_CLK_SEL (ADC_CLK_SYS_CLK)
|
||||
|
||||
#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK)
|
||||
#define ADC_CLK (CLK_PERIPHCLK_PCLK)
|
||||
|
||||
#elif (ADC_CLK_SEL == ADC_CLK_PLLH)
|
||||
#define ADC_CLK (CLK_PERIPHCLK_PLLQ)
|
||||
|
||||
#elif (ADC_CLK_SEL == ADC_CLK_PLLA)
|
||||
#define ADC_CLK (CLK_PERIPHCLK_PLLXP)
|
||||
|
||||
#else
|
||||
#error "The clock source your selected does not exist!!!"
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_ADC2
|
||||
#define ADC2_GPIO ADC_CONS(GPIO_Pin_, ADC2_GPIO_NUM)
|
||||
#endif
|
||||
/* ADC unit instance for this example. */
|
||||
#define ADC_UNIT (CM_ADC1)
|
||||
#define ADC_PERIPH_CLK (FCG3_PERIPH_ADC1)
|
||||
|
||||
#ifdef BSP_USING_ADC3
|
||||
#define ADC3_GPIO ADC_CONS(GPIO_Pin_, ADC3_GPIO_NUM)
|
||||
#endif
|
||||
/* Selects ADC channels that needed. */
|
||||
#define ADC_CH_POTENTIOMETER (ADC_CH3)
|
||||
#define ADC_CH (ADC_CH_POTENTIOMETER)
|
||||
#define ADC_CH_PORT (GPIO_PORT_A)
|
||||
#define ADC_CH_PIN (GPIO_PIN_03)
|
||||
|
||||
static int AdcUdelay(uint32 us)
|
||||
/* ADC sequence to be used. */
|
||||
#define ADC_SEQ (ADC_SEQ_A)
|
||||
/* Flag of conversion end. */
|
||||
#define ADC_EOC_FLAG (ADC_FLAG_EOCA)
|
||||
|
||||
/* ADC reference voltage. The voltage of pin VREFH. */
|
||||
#define ADC_VREF (3.3F)
|
||||
|
||||
/* ADC accuracy(according to the resolution of ADC). */
|
||||
#define ADC_ACCURACY (1UL << 12U)
|
||||
|
||||
/* Calculate the voltage(mV). */
|
||||
#define ADC_CAL_VOL(adcVal) (uint16_t)((((float32_t)(adcVal) * ADC_VREF) / ((float32_t)ADC_ACCURACY)) * 1000.F)
|
||||
|
||||
/* Timeout value. */
|
||||
#define ADC_TIMEOUT_VAL (1000U)
|
||||
|
||||
/**
|
||||
* @brief Set specified ADC pin to analog mode.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void AdcSetPinAnalogMode(void)
|
||||
{
|
||||
uint32 ticks;
|
||||
uint32 told, tnow, tcnt = 0;
|
||||
uint32 reload = SysTick->LOAD;
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
|
||||
ticks = us * reload / (1000000 / TICK_PER_SECOND);
|
||||
told = SysTick->VAL;
|
||||
while (1) {
|
||||
tnow = SysTick->VAL;
|
||||
if (tnow != told) {
|
||||
if (tnow < told) {
|
||||
tcnt += told - tnow;
|
||||
} else {
|
||||
tcnt += reload - tnow + told;
|
||||
}
|
||||
told = tnow;
|
||||
if (tcnt >= ticks) {
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG;
|
||||
(void)GPIO_Init(ADC_CH_PORT, ADC_CH_PIN, &stcGpioInit);
|
||||
}
|
||||
|
||||
static uint16 GetAdcAverageValue(CM_ADC_TypeDef *ADCx, uint8 channel, uint8 times)
|
||||
/**
|
||||
* @brief Configures ADC clock.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void AdcClockConfig(void)
|
||||
{
|
||||
uint32 temp_val = 0;
|
||||
int i;
|
||||
#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK)
|
||||
/*
|
||||
* 1. Configures the clock divider of PCLK2 and PCLK4 here or in the function of configuring the system clock.
|
||||
* In this example, the system clock is MRC@8MHz.
|
||||
* PCLK4 is the digital interface clock, and PCLK2 is the analog circuit clock.
|
||||
* Make sure that PCLK2 and PCLK4 meet the following conditions:
|
||||
* PCLK4 : PCLK2 = 1:1, 2:1, 4:1, 8:1, 1:2, 1:4.
|
||||
* PCLK2 is in range [1MHz, 60MHz].
|
||||
*/
|
||||
CLK_SetClockDiv((CLK_BUS_PCLK2 | CLK_BUS_PCLK4), (CLK_PCLK2_DIV8 | CLK_PCLK4_DIV2));
|
||||
|
||||
for(i = 0;i < times;i ++) {
|
||||
temp_val += ADC_GetValue(ADCx, channel) & 0x0FFF;
|
||||
KPrintf("GetAdcAverageValue val %u\n", ADC_GetValue(ADCx, channel));
|
||||
AdcUdelay(5000);
|
||||
}
|
||||
return temp_val / times;
|
||||
}
|
||||
#elif (ADC_CLK_SEL == ADC_CLK_PLLH)
|
||||
/*
|
||||
* 1. Configures PLLH and the divider of PLLHx(x=Q, R).
|
||||
* PLLHx(x=Q, R) is used as both the digital interface clock and the analog circuit clock.
|
||||
* PLLHx(x=Q, R) must be in range [1MHz, 60MHz] for ADC use.
|
||||
* The input source of PLLH is XTAL(8MHz).
|
||||
*/
|
||||
stc_clock_pll_init_t stcPLLHInit;
|
||||
stc_clock_xtal_init_t stcXtalInit;
|
||||
|
||||
/* Configures XTAL. PLLH input source is XTAL. */
|
||||
(void)CLK_XtalStructInit(&stcXtalInit);
|
||||
stcXtalInit.u8State = CLK_XTAL_ON;
|
||||
stcXtalInit.u8Drv = CLK_XTAL_DRV_ULOW;
|
||||
stcXtalInit.u8Mode = CLK_XTAL_MD_OSC;
|
||||
stcXtalInit.u8StableTime = CLK_XTAL_STB_499US;
|
||||
(void)CLK_XtalInit(&stcXtalInit);
|
||||
|
||||
(void)CLK_PLLStructInit(&stcPLLHInit);
|
||||
/*
|
||||
* PLLHx(x=Q, R) = ((PLL_source / PLLM) * PLLN) / PLLx
|
||||
* PLLHQ = (8 / 1) * 80 /16 = 40MHz
|
||||
* PLLHR = (8 / 1) * 80 /16 = 40MHz
|
||||
*/
|
||||
stcPLLHInit.u8PLLState = CLK_PLL_ON;
|
||||
stcPLLHInit.PLLCFGR = 0UL;
|
||||
stcPLLHInit.PLLCFGR_f.PLLM = (1UL - 1UL);
|
||||
stcPLLHInit.PLLCFGR_f.PLLN = (80UL - 1UL);
|
||||
stcPLLHInit.PLLCFGR_f.PLLP = (4UL - 1UL);
|
||||
stcPLLHInit.PLLCFGR_f.PLLQ = (16UL - 1UL);
|
||||
stcPLLHInit.PLLCFGR_f.PLLR = (16UL - 1UL);
|
||||
/* stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL; */
|
||||
(void)CLK_PLLInit(&stcPLLHInit);
|
||||
|
||||
#elif (ADC_CLK_SEL == ADC_CLK_PLLA)
|
||||
/*
|
||||
* 1. Configures PLLA and the divider of PLLAx(x=P, Q, R).
|
||||
* PLLAx(x=P, Q, R) is used as both the digital interface clock and the analog circuit clock.
|
||||
* PLLAx(x=P, Q, R) must be in range [1MHz, 60MHz] for ADC use.
|
||||
* The input source of PLLA is HRC(16MHz).
|
||||
*/
|
||||
stc_clock_pllx_init_t stcPLLAInit;
|
||||
|
||||
/* Enable HRC(16MHz) for PLLA. */
|
||||
CLK_HrcCmd(ENABLE);
|
||||
|
||||
/* Specify the input source of PLLA. NOTE!!! PLLA and PLLH use the same input source. */
|
||||
CLK_SetPLLSrc(CLK_PLL_SRC_HRC);
|
||||
/* PLLA configuration */
|
||||
(void)CLK_PLLxStructInit(&stcPLLAInit);
|
||||
/*
|
||||
* PLLAx(x=P, Q, R) = ((PLL_source / PLLM) * PLLN) / PLLx
|
||||
* PLLAP = (16 / 2) * 40 / 8 = 40MHz
|
||||
* PLLAQ = (16 / 2) * 40 / 10 = 32MHz
|
||||
* PLLAR = (16 / 2) * 40 / 16 = 20MHz
|
||||
*/
|
||||
stcPLLAInit.u8PLLState = CLK_PLLX_ON;
|
||||
stcPLLAInit.PLLCFGR = 0UL;
|
||||
stcPLLAInit.PLLCFGR_f.PLLM = (2UL - 1UL);
|
||||
stcPLLAInit.PLLCFGR_f.PLLN = (40UL - 1UL);
|
||||
stcPLLAInit.PLLCFGR_f.PLLR = (8UL - 1UL);
|
||||
stcPLLAInit.PLLCFGR_f.PLLQ = (10UL - 1UL);
|
||||
stcPLLAInit.PLLCFGR_f.PLLP = (16UL - 1UL);
|
||||
(void)CLK_PLLxInit(&stcPLLAInit);
|
||||
#endif
|
||||
/* 2. Specifies the clock source of ADC. */
|
||||
CLK_SetPeriClockSrc(ADC_CLK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes ADC.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void AdcInitConfig(void)
|
||||
{
|
||||
stc_adc_init_t stcAdcInit;
|
||||
|
||||
/* 1. Enable ADC peripheral clock. */
|
||||
FCG_Fcg3PeriphClockCmd(ADC_PERIPH_CLK, ENABLE);
|
||||
|
||||
/* 2. Modify the default value depends on the application. Not needed here. */
|
||||
(void)ADC_StructInit(&stcAdcInit);
|
||||
|
||||
/* 3. Initializes ADC. */
|
||||
(void)ADC_Init(ADC_UNIT, &stcAdcInit);
|
||||
|
||||
/* 4. ADC channel configuration. */
|
||||
/* 4.1 Set the ADC pin to analog input mode. */
|
||||
AdcSetPinAnalogMode();
|
||||
/* 4.2 Enable ADC channels. Call ADC_ChCmd() again to enable more channels if needed. */
|
||||
ADC_ChCmd(ADC_UNIT, ADC_SEQ, ADC_CH, ENABLE);
|
||||
|
||||
/* 5. Conversion data average calculation function, if needed.
|
||||
Call ADC_ConvDataAverageChCmd() again to enable more average channels if needed. */
|
||||
ADC_ConvDataAverageConfig(ADC_UNIT, ADC_AVG_CNT8);
|
||||
ADC_ConvDataAverageChCmd(ADC_UNIT, ADC_CH, ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Use ADC in polling mode.
|
||||
* @param None
|
||||
* @retval uint16_t u16AdcValue
|
||||
*/
|
||||
static uint16_t AdcPolling(void)
|
||||
{
|
||||
uint16_t u16AdcValue = 0;
|
||||
int32_t iRet = LL_ERR;
|
||||
__IO uint32_t u32TimeCount = 0UL;
|
||||
|
||||
/* Can ONLY start sequence A conversion.
|
||||
Sequence B needs hardware trigger to start conversion. */
|
||||
ADC_Start(ADC_UNIT);
|
||||
do {
|
||||
if (ADC_GetStatus(ADC_UNIT, ADC_EOC_FLAG) == SET) {
|
||||
ADC_ClearStatus(ADC_UNIT, ADC_EOC_FLAG);
|
||||
iRet = LL_OK;
|
||||
break;
|
||||
}
|
||||
} while (u32TimeCount++ < ADC_TIMEOUT_VAL);
|
||||
|
||||
if (iRet == LL_OK) {
|
||||
/* Get any ADC value of sequence A channel that needed. */
|
||||
u16AdcValue = ADC_GetValue(ADC_UNIT, ADC_CH);
|
||||
KPrintf("The ADC value of potentiometer is %u, voltage is %u mV\r\n",
|
||||
u16AdcValue, ADC_CAL_VOL(u16AdcValue));
|
||||
} else {
|
||||
ADC_Stop(ADC_UNIT);
|
||||
KPrintf("ADC exception.\r\n");
|
||||
}
|
||||
|
||||
return ADC_CAL_VOL(u16AdcValue);
|
||||
}
|
||||
|
||||
static uint32 AdcOpen(void *dev)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
stc_adc_init_t stcAdcInit;
|
||||
ADC_StructInit(&stcAdcInit);
|
||||
struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev;
|
||||
CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data;
|
||||
ADC_Init((ADCx),&stcAdcInit);
|
||||
|
||||
AdcClockConfig();
|
||||
AdcInitConfig();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint32 AdcClose(void *dev)
|
||||
{
|
||||
// CM_ADC_TypeDef *adc_dev = (CM_ADC_TypeDef*)dev;
|
||||
struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev;
|
||||
|
||||
CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data;
|
||||
|
||||
|
||||
ADC_Stop(ADC_UNIT);
|
||||
ADC_DeInit(ADCx);
|
||||
|
||||
return EOK;
|
||||
|
@ -100,19 +272,10 @@ static uint32 AdcClose(void *dev)
|
|||
|
||||
static uint32 AdcRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
{
|
||||
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
|
||||
*(uint16 *)read_param->buffer = AdcPolling();
|
||||
read_param->read_length = 2;
|
||||
|
||||
struct HwAdc *adc_cfg = (struct HwAdc *)adc_dev->haldev.private_data;
|
||||
|
||||
uint16 adc_average_value = 0;
|
||||
uint8 times = 20;
|
||||
|
||||
adc_average_value = GetAdcAverageValue(adc_cfg->ADCx, adc_cfg->adc_channel, times);
|
||||
|
||||
*(uint16 *)read_param->buffer = adc_average_value;
|
||||
read_param->read_length = 2;
|
||||
|
||||
return read_param->read_length;
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
|
@ -131,9 +294,9 @@ static uint32 AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info
|
|||
{
|
||||
case OPE_CFG:
|
||||
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
|
||||
if (adc_cfg->adc_channel > 18) {
|
||||
KPrintf("AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel);
|
||||
adc_cfg->adc_channel = 0;
|
||||
if (adc_cfg->adc_channel != 1) {
|
||||
KPrintf("AdcDrvConfigure set adc channel(1) %u error!", adc_cfg->adc_channel);
|
||||
adc_cfg->adc_channel = 1;
|
||||
ret = ERROR;
|
||||
}
|
||||
break;
|
||||
|
@ -156,7 +319,7 @@ int HwAdcInit(void)
|
|||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
#ifdef BSP_USING_ADC1
|
||||
#ifdef BSP_USING_ADC
|
||||
static struct AdcBus adc1_bus;
|
||||
static struct AdcDriver adc1_drv;
|
||||
static struct AdcHardwareDevice adc1_dev;
|
||||
|
@ -183,7 +346,7 @@ int HwAdcInit(void)
|
|||
|
||||
adc1_dev.adc_dev_done = &dev_done;
|
||||
adc1_cfg.ADCx = CM_ADC1;
|
||||
adc1_cfg.adc_channel = 0;
|
||||
adc1_cfg.adc_channel = 1;
|
||||
|
||||
ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEVICE_NAME);
|
||||
if (ret != EOK) {
|
||||
|
@ -197,88 +360,6 @@ int HwAdcInit(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_ADC2
|
||||
static struct AdcBus adc2_bus;
|
||||
static struct AdcDriver adc2_drv;
|
||||
static struct AdcHardwareDevice adc2_dev;
|
||||
static struct HwAdc adc2_cfg;
|
||||
|
||||
adc2_drv.configure = AdcDrvConfigure;
|
||||
|
||||
ret = AdcBusInit(&adc2_bus, ADC2_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC2 bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = AdcDriverInit(&adc2_drv, ADC2_DRIVER_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC2 driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = AdcDriverAttachToBus(ADC2_DRIVER_NAME, ADC2_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC2 driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
adc2_dev.adc_dev_done = &dev_done;
|
||||
adc2_cfg.ADCx = CM_ADC2;
|
||||
adc2_cfg.adc_channel = 0;
|
||||
|
||||
ret = AdcDeviceRegister(&adc2_dev, (void *)&adc2_cfg, ADC2_DEVICE_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC2 device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = AdcDeviceAttachToBus(ADC2_DEVICE_NAME, ADC2_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC2 device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_ADC3
|
||||
static struct AdcBus adc3_bus;
|
||||
static struct AdcDriver adc3_drv;
|
||||
static struct AdcHardwareDevice adc3_dev;
|
||||
static struct HwAdc adc3_cfg;
|
||||
|
||||
adc3_drv.configure = AdcDrvConfigure;
|
||||
|
||||
ret = AdcBusInit(&adc3_bus, ADC3_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC3 bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = AdcDriverInit(&adc3_drv, ADC3_DRIVER_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC3 driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = AdcDriverAttachToBus(ADC3_DRIVER_NAME, ADC3_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC3 driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
adc3_dev.adc_dev_done = &dev_done;
|
||||
adc3_cfg.ADCx = CM_ADC3;
|
||||
adc3_cfg.adc_channel = 0;
|
||||
|
||||
ret = AdcDeviceRegister(&adc3_dev, (void *)&adc3_cfg, ADC3_DEVICE_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC3 device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
ret = AdcDeviceAttachToBus(ADC3_DEVICE_NAME, ADC3_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("ADC3 device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ ifeq ($(CONFIG_BSP_USING_ADC),y)
|
|||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_DAC),y)
|
||||
SRC_FILES += hc32_ll_dac.c
|
||||
SRC_FILES += hc32_ll_dac.c hc32_ll_mau.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BSP_USING_SDIO),y)
|
||||
|
|
|
@ -20,56 +20,301 @@
|
|||
|
||||
#include <connect_dac.h>
|
||||
|
||||
#define _DAC_CONS(string1, string2) string1##string2
|
||||
#define DAC_CONS(string1, string2) _DAC_CONS(string1, string2)
|
||||
/*******************************************************************************
|
||||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
#define DAC_UNIT1_PORT (GPIO_PORT_A)
|
||||
#define DAC_UNIT1_CHN1_PIN (GPIO_PIN_04)
|
||||
|
||||
#ifdef BSP_USING_DAC
|
||||
#define DAC_GPIO DAC_CONS(GPIO_Pin_, DAC_GPIO_NUM)
|
||||
#define VREFH (3.3F)
|
||||
#define DAC_CHN1 (0U)
|
||||
#define DAC_CHN2 (1U)
|
||||
#define DAC_DATA_ALIGN_12b_R (0U)
|
||||
#define DAC_DATA_ALIGN_12b_L (1U)
|
||||
|
||||
#define SUPPORT_AMP
|
||||
#define SUPPORT_ADP
|
||||
#define SINGLE_WAVE_DAC_CHN (DAC_CHN1)
|
||||
#define DAC_DATA_ALIGN (DAC_DATA_ALIGN_12b_L)
|
||||
|
||||
#define SINE_DOT_NUMBER (4096U)
|
||||
#define SINE_NEGATIVE_TO_POSITVE (1.0F)
|
||||
|
||||
/*******************************************************************************
|
||||
* Local type definitions ('typedef')
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
DAC_Unit1,
|
||||
DAC_Unit2,
|
||||
DAC_Unit_Max,
|
||||
}en_dac_unit_t;
|
||||
|
||||
typedef enum {
|
||||
E_Dac_Single,
|
||||
E_Dac_Dual,
|
||||
}en_dac_cvt_t;
|
||||
|
||||
typedef struct {
|
||||
CM_DAC_TypeDef *pUnit;
|
||||
en_dac_cvt_t enCvtType;
|
||||
uint16_t u16Ch;
|
||||
} stc_dac_handle_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
static stc_dac_handle_t m_stcDACHandle[DAC_Unit_Max] = {0};
|
||||
static uint32_t gu32SinTable[SINE_DOT_NUMBER];
|
||||
static stc_dac_handle_t *pSingleDac;
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
/**
|
||||
* @brief MAU Initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MauInit(void)
|
||||
{
|
||||
/* Enable MAU peripheral clock. */
|
||||
FCG_Fcg0PeriphClockCmd(PWC_FCG0_MAU, ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MAU De-Initialization
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MauDeinit(void)
|
||||
{
|
||||
/* Enable MAU peripheral clock. */
|
||||
FCG_Fcg0PeriphClockCmd(PWC_FCG0_MAU, DISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sin table Initialization
|
||||
* @param [in] pSinTable sin table
|
||||
* @param [in] u32count number of pSinTable items
|
||||
* @retval None
|
||||
*/
|
||||
static void SinTableInit(uint32_t pSinTable[], uint32_t u32count)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t u32AngAvg = (uint32_t)(float32_t)((float32_t)((float32_t)MAU_SIN_ANGIDX_TOTAL / (float32_t)u32count) + 0.5);
|
||||
float32_t fSin;
|
||||
for (i = 0U; i < u32count; i++) {
|
||||
fSin = (((float32_t)MAU_Sin(CM_MAU, (uint16_t)(u32AngAvg * i))
|
||||
/ (float32_t)MAU_SIN_Q15_SCALAR + SINE_NEGATIVE_TO_POSITVE) / VREFH) *
|
||||
(float32_t)DAC_DATAREG_VALUE_MAX + 0.5F;
|
||||
|
||||
#if (DAC_DATA_ALIGN == DAC_DATA_ALIGN_12b_L)
|
||||
{
|
||||
pSinTable[i] = (uint32_t)fSin << 4;
|
||||
}
|
||||
#else
|
||||
{
|
||||
pSinTable[i] = (uint32_t)fSin;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DAC peripheral clock
|
||||
* @param [in] enUnit The selected DAC unit
|
||||
* @retval None
|
||||
*/
|
||||
static void DacPClkEnable(en_dac_unit_t enUnit)
|
||||
{
|
||||
uint32_t u32PClk;
|
||||
switch (enUnit) {
|
||||
case DAC_Unit1:
|
||||
u32PClk = PWC_FCG3_DAC1;
|
||||
break;
|
||||
case DAC_Unit2:
|
||||
u32PClk = PWC_FCG3_DAC2;
|
||||
break;
|
||||
default:
|
||||
u32PClk = PWC_FCG3_DAC1 | PWC_FCG3_DAC2;
|
||||
break;
|
||||
}
|
||||
/* Enable DAC peripheral clock. */
|
||||
FCG_Fcg3PeriphClockCmd(u32PClk, ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init DAC single channel
|
||||
* @param [in] enUnit The selected DAC unit
|
||||
* @retval A pointer of DAC handler
|
||||
*/
|
||||
static stc_dac_handle_t *DacSingleConversionInit(en_dac_unit_t enUnit)
|
||||
{
|
||||
uint8_t u8Port;
|
||||
uint16_t u16Pin;
|
||||
stc_dac_handle_t *pDac;
|
||||
|
||||
if (enUnit == DAC_Unit1) {
|
||||
pDac = &m_stcDACHandle[DAC_Unit1];
|
||||
pDac->pUnit = CM_DAC1;
|
||||
} else {
|
||||
pDac = &m_stcDACHandle[DAC_Unit2];
|
||||
pDac->pUnit = CM_DAC2;
|
||||
}
|
||||
DacPClkEnable(enUnit);
|
||||
|
||||
pDac->enCvtType = E_Dac_Single;
|
||||
#if (SINGLE_WAVE_DAC_CHN == DAC_CHN1)
|
||||
pDac->u16Ch = DAC_CH1;
|
||||
#else
|
||||
pDac->u16Ch = DAC_CH2;
|
||||
#endif
|
||||
|
||||
/* Init DAC by default value: source from data register and output enabled*/
|
||||
DAC_DeInit(pDac->pUnit);
|
||||
stc_dac_init_t stInit;
|
||||
(void)DAC_StructInit(&stInit);
|
||||
(void)DAC_Init(pDac->pUnit, pDac->u16Ch, &stInit);
|
||||
#if (DAC_DATA_ALIGN == DAC_DATA_ALIGN_12b_L)
|
||||
DAC_DataRegAlignConfig(pDac->pUnit, DAC_DATA_ALIGN_L);
|
||||
#else
|
||||
DAC_DataRegAlignConfig(pDac->pUnit, DAC_DATA_ALIGN_R);
|
||||
#endif
|
||||
|
||||
/* Set DAC pin attribute to analog */
|
||||
if (enUnit == DAC_Unit1) {
|
||||
u8Port = DAC_UNIT1_PORT;
|
||||
#if (SINGLE_WAVE_DAC_CHN == DAC_CHN1)
|
||||
u16Pin = DAC_UNIT1_CHN1_PIN;
|
||||
#endif
|
||||
}
|
||||
stc_gpio_init_t stcGpioInit;
|
||||
(void)GPIO_StructInit(&stcGpioInit);
|
||||
stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG;
|
||||
(void)GPIO_Init(u8Port, u16Pin, &stcGpioInit);
|
||||
|
||||
#ifdef SUPPORT_ADP
|
||||
/* Set ADC first */
|
||||
/* Enable ADC peripheral clock. */
|
||||
FCG_Fcg3PeriphClockCmd(PWC_FCG3_ADC1 | PWC_FCG3_ADC2 | PWC_FCG3_ADC3, ENABLE);
|
||||
if (CM_ADC1->STR == 0U) {
|
||||
if (CM_ADC2->STR == 0U) {
|
||||
if (CM_ADC3->STR == 0U) {
|
||||
DAC_ADCPrioConfig(pDac->pUnit, DAC_ADP_SELECT_ALL, ENABLE);
|
||||
DAC_ADCPrioCmd(pDac->pUnit, ENABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return pDac;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start single DAC conversions
|
||||
* @param [in] pDac A pointer of DAC handler
|
||||
* @retval None
|
||||
*/
|
||||
static void DacStartSingleConversion(const stc_dac_handle_t *pDac)
|
||||
{
|
||||
/* Enalbe AMP */
|
||||
#ifdef SUPPORT_AMP
|
||||
(void)DAC_AMPCmd(pDac->pUnit, pDac->u16Ch, ENABLE);
|
||||
#endif
|
||||
|
||||
(void)DAC_Start(pDac->pUnit, pDac->u16Ch);
|
||||
|
||||
#ifdef SUPPORT_AMP
|
||||
/* delay 3us before setting data*/
|
||||
DDL_DelayMS(1U);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert data by single DAC channel
|
||||
* @param [in] pDac A pointer of DAC handler
|
||||
* @param [in] pDataTable The data table to be converted
|
||||
* @param [in] u32count Number of data table items
|
||||
* @retval None
|
||||
*/
|
||||
__STATIC_INLINE void DacSetSingleConversionData(const stc_dac_handle_t *pDac, uint32_t const pDataTable[], uint32_t u32count)
|
||||
{
|
||||
uint32_t i = 0U;
|
||||
|
||||
for (i = 0U; i < u32count; i++) {
|
||||
#ifdef SUPPORT_ADP
|
||||
uint32_t u32TryCount = 100U;
|
||||
while (u32TryCount != 0U) {
|
||||
u32TryCount--;
|
||||
if (SET != DAC_GetChConvertState(pDac->pUnit, pDac->u16Ch)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DAC_SetChData(pDac->pUnit, pDac->u16Ch, (uint16_t)pDataTable[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief stop DAC conversion
|
||||
* @param [in] pDac A pointer of DAC handler
|
||||
* @retval None
|
||||
*/
|
||||
static void DAC_StopConversion(const stc_dac_handle_t *pDac)
|
||||
{
|
||||
if (NULL == pDac) {
|
||||
DAC_DeInit(CM_DAC1);
|
||||
DAC_DeInit(CM_DAC2);
|
||||
} else if (pDac->enCvtType != E_Dac_Dual) {
|
||||
(void)DAC_Stop(pDac->pUnit, pDac->u16Ch);
|
||||
} else {
|
||||
DAC_StopDualCh(pDac->pUnit);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 DacOpen(void *dev)
|
||||
{
|
||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
||||
|
||||
CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data;
|
||||
/* Init MAU for generating sine data*/
|
||||
MauInit();
|
||||
/* Init sine data table */
|
||||
SinTableInit(gu32SinTable, SINE_DOT_NUMBER);
|
||||
|
||||
stc_dac_init_t pstcDacInit;
|
||||
|
||||
DAC_StructInit(&pstcDacInit);
|
||||
|
||||
DAC_Init(DACx,DAC_CH1,&pstcDacInit);
|
||||
/* Init single DAC */
|
||||
pSingleDac = DacSingleConversionInit(DAC_Unit1);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 DacClose(void *dev)
|
||||
{
|
||||
|
||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
||||
|
||||
CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data;
|
||||
|
||||
|
||||
DAC_StopConversion(pSingleDac);
|
||||
|
||||
DAC_DeInit(DACx);
|
||||
|
||||
MauDeinit();
|
||||
|
||||
memset(gu32SinTable, 0 , sizeof(gu32SinTable));
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
|
||||
static uint32 DacRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
static uint32 DacWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||
{
|
||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
||||
struct HwDac *dac_cfg = (struct HwDac *)dac_dev->haldev.private_data;
|
||||
|
||||
CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data;
|
||||
for (int i = 0; i < dac_cfg->digital_data; i ++) {
|
||||
DacStartSingleConversion(pSingleDac);
|
||||
DacSetSingleConversionData(pSingleDac, &gu32SinTable[i], 1U);
|
||||
if (i > SINE_DOT_NUMBER) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 dac_set_value = 0;
|
||||
|
||||
dac_set_value = DAC_GetChConvertState(DACx,DAC_CH1);
|
||||
|
||||
*(uint16 *)read_param->buffer = dac_set_value;
|
||||
read_param->read_length = 2;
|
||||
|
||||
return read_param->read_length;
|
||||
return EOK;
|
||||
}
|
||||
|
||||
|
@ -88,8 +333,6 @@ static uint32 DacDrvConfigure(void *drv, struct BusConfigureInfo *configure_info
|
|||
{
|
||||
case OPE_CFG:
|
||||
dac_cfg->digital_data = *(uint16 *)configure_info->private_data;
|
||||
// DAC_SetChannel1Data(DAC_Align_12b_R, dac_cfg->digital_data);//12 bits、R-Align data format, digital data
|
||||
DAC_SetChData(dac_cfg->DACx,DAC_CH1,dac_cfg->digital_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -102,8 +345,8 @@ static const struct DacDevDone dev_done =
|
|||
{
|
||||
DacOpen,
|
||||
DacClose,
|
||||
DacWrite,
|
||||
NONE,
|
||||
DacRead,
|
||||
};
|
||||
|
||||
int HwDacInit(void)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := ethernetif.c eth_driver.c
|
||||
SRC_FILES := ethernetif.c eth_driver.c eth_netdev.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
/**
|
||||
* @file ethernetif.c
|
||||
* @brief support edu-arm32-board ethernetif function and register to Lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
* @file ethernetif.c
|
||||
* @brief support hc32f4a0-board ethernetif function and register to Lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <hc32_ll_fcg.h>
|
||||
#include <hc32_ll_gpio.h>
|
||||
#include <hc32_ll_utility.h>
|
||||
#include <hc32_ll_fcg.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <netif/etharp.h>
|
||||
|
||||
#include <sys_arch.h>
|
||||
|
||||
void eth_irq_handler(void) {
|
||||
void eth_irq_handler(void)
|
||||
{
|
||||
static x_base eth_irq_lock;
|
||||
eth_irq_lock = DISABLE_INTERRUPT();
|
||||
|
||||
|
@ -24,7 +25,7 @@ void eth_irq_handler(void) {
|
|||
sys_sem_signal(get_eth_recv_sem());
|
||||
ETH_DMA_ClearStatus(ETH_DMA_FLAG_RIS | ETH_DMA_FLAG_NIS);
|
||||
}
|
||||
|
||||
|
||||
ENABLE_INTERRUPT(eth_irq_lock);
|
||||
}
|
||||
|
||||
|
@ -35,7 +36,7 @@ void eth_irq_handler(void) {
|
|||
* - LL_OK: Initialize success
|
||||
* - LL_ERR: Initialize failed
|
||||
*/
|
||||
int32_t low_level_init(struct netif *netif)
|
||||
int32_t low_level_init(struct netif* netif)
|
||||
{
|
||||
int32_t i32Ret = LL_ERR;
|
||||
stc_eth_init_t stcEthInit;
|
||||
|
@ -52,9 +53,9 @@ int32_t low_level_init(struct netif *netif)
|
|||
(void)ETH_StructInit(&stcEthInit);
|
||||
|
||||
#ifdef ETH_INTERFACE_RMII
|
||||
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII;
|
||||
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_RMII;
|
||||
#else
|
||||
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII;
|
||||
EthHandle.stcCommInit.u32Interface = ETH_MAC_IF_MII;
|
||||
#endif
|
||||
// stcEthInit.stcMacInit.u32ReceiveAll = ETH_MAC_RX_ALL_ENABLE;
|
||||
EthHandle.stcCommInit.u32ReceiveMode = ETH_RX_MD_INT;
|
||||
|
@ -125,7 +126,7 @@ int32_t low_level_init(struct netif *netif)
|
|||
u16RegVal = PHY_PAGE_ADDR_0;
|
||||
(void)ETH_PHY_WriteReg(&EthHandle, PHY_PSR, u16RegVal);
|
||||
#endif
|
||||
|
||||
|
||||
return i32Ret;
|
||||
}
|
||||
|
||||
|
@ -137,19 +138,19 @@ int32_t low_level_init(struct netif *netif)
|
|||
* - LL_OK: The packet could be sent
|
||||
* - LL_ERR: The packet couldn't be sent
|
||||
*/
|
||||
err_t low_level_output(struct netif *netif, struct pbuf *p)
|
||||
err_t low_level_output(struct netif* netif, struct pbuf* p)
|
||||
{
|
||||
err_t i32Ret;
|
||||
struct pbuf *q;
|
||||
uint8_t *txBuffer;
|
||||
__IO stc_eth_dma_desc_t *DmaTxDesc;
|
||||
struct pbuf* q;
|
||||
uint8_t* txBuffer;
|
||||
__IO stc_eth_dma_desc_t* DmaTxDesc;
|
||||
uint32_t byteCnt;
|
||||
uint32_t frameLength = 0UL;
|
||||
uint32_t bufferOffset;
|
||||
uint32_t payloadOffset;
|
||||
|
||||
DmaTxDesc = EthHandle.stcTxDesc;
|
||||
txBuffer = (uint8_t *)((EthHandle.stcTxDesc)->u32Buf1Addr);
|
||||
txBuffer = (uint8_t*)((EthHandle.stcTxDesc)->u32Buf1Addr);
|
||||
bufferOffset = 0UL;
|
||||
/* Copy frame from pbufs to driver buffers */
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
|
@ -165,28 +166,28 @@ err_t low_level_output(struct netif *netif, struct pbuf *p)
|
|||
/* Check if the length of data to copy is bigger than Tx buffer size */
|
||||
while ((byteCnt + bufferOffset) > ETH_TX_BUF_SIZE) {
|
||||
/* Copy data to Tx buffer*/
|
||||
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset));
|
||||
(void)memcpy((uint8_t*)&(txBuffer[bufferOffset]), (uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (ETH_TX_BUF_SIZE - bufferOffset));
|
||||
/* Point to next descriptor */
|
||||
DmaTxDesc = (stc_eth_dma_desc_t *)(DmaTxDesc->u32Buf2NextDescAddr);
|
||||
DmaTxDesc = (stc_eth_dma_desc_t*)(DmaTxDesc->u32Buf2NextDescAddr);
|
||||
/* Check if the buffer is available */
|
||||
if (0UL != (DmaTxDesc->u32ControlStatus & ETH_DMA_TXDESC_OWN)) {
|
||||
i32Ret = (err_t)ERR_USE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
txBuffer = (uint8_t *)(DmaTxDesc->u32Buf1Addr);
|
||||
txBuffer = (uint8_t*)(DmaTxDesc->u32Buf1Addr);
|
||||
byteCnt = byteCnt - (ETH_TX_BUF_SIZE - bufferOffset);
|
||||
payloadOffset = payloadOffset + (ETH_TX_BUF_SIZE - bufferOffset);
|
||||
frameLength = frameLength + (ETH_TX_BUF_SIZE - bufferOffset);
|
||||
bufferOffset = 0UL;
|
||||
}
|
||||
/* Copy the remaining bytes */
|
||||
(void)memcpy((uint8_t *) & (txBuffer[bufferOffset]), (uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), byteCnt);
|
||||
(void)memcpy((uint8_t*)&(txBuffer[bufferOffset]), (uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), byteCnt);
|
||||
bufferOffset = bufferOffset + byteCnt;
|
||||
frameLength = frameLength + byteCnt;
|
||||
}
|
||||
/* Prepare transmit descriptors to give to DMA */
|
||||
if(LL_OK != ETH_DMA_SetTransFrame(&EthHandle, frameLength)) {
|
||||
if (LL_OK != ETH_DMA_SetTransFrame(&EthHandle, frameLength)) {
|
||||
KPrintf("[%s] Error sending eth DMA frame\n", __func__);
|
||||
}
|
||||
i32Ret = (err_t)ERR_OK;
|
||||
|
@ -208,13 +209,13 @@ error:
|
|||
* @param netif The network interface structure for this ethernetif.
|
||||
* @retval A pbuf filled with the received packet (including MAC header) or NULL on memory error.
|
||||
*/
|
||||
struct pbuf *low_level_input(struct netif *netif)
|
||||
struct pbuf* low_level_input(struct netif* netif)
|
||||
{
|
||||
struct pbuf *p = NULL;
|
||||
struct pbuf *q;
|
||||
struct pbuf* p = NULL;
|
||||
struct pbuf* q;
|
||||
uint32_t len;
|
||||
uint8_t *rxBuffer;
|
||||
__IO stc_eth_dma_desc_t *DmaRxDesc;
|
||||
uint8_t* rxBuffer;
|
||||
__IO stc_eth_dma_desc_t* DmaRxDesc;
|
||||
uint32_t byteCnt;
|
||||
uint32_t bufferOffset;
|
||||
uint32_t payloadOffset;
|
||||
|
@ -227,7 +228,7 @@ struct pbuf *low_level_input(struct netif *netif)
|
|||
|
||||
/* Obtain the size of the packet */
|
||||
len = (EthHandle.stcRxFrame).u32Len;
|
||||
rxBuffer = (uint8_t *)(EthHandle.stcRxFrame).u32Buf;
|
||||
rxBuffer = (uint8_t*)(EthHandle.stcRxFrame).u32Buf;
|
||||
if (len > 0UL) {
|
||||
/* Allocate a pbuf chain of pbufs from the buffer */
|
||||
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
|
||||
|
@ -243,17 +244,17 @@ struct pbuf *low_level_input(struct netif *netif)
|
|||
/* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size */
|
||||
while ((byteCnt + bufferOffset) > ETH_RX_BUF_SIZE) {
|
||||
/* Copy data to pbuf */
|
||||
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset));
|
||||
(void)memcpy((uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (uint8_t*)&(rxBuffer[bufferOffset]), (ETH_RX_BUF_SIZE - bufferOffset));
|
||||
/* Point to next descriptor */
|
||||
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
|
||||
rxBuffer = (uint8_t *)(DmaRxDesc->u32Buf1Addr);
|
||||
DmaRxDesc = (stc_eth_dma_desc_t*)(DmaRxDesc->u32Buf2NextDescAddr);
|
||||
rxBuffer = (uint8_t*)(DmaRxDesc->u32Buf1Addr);
|
||||
byteCnt = byteCnt - (ETH_RX_BUF_SIZE - bufferOffset);
|
||||
payloadOffset = payloadOffset + (ETH_RX_BUF_SIZE - bufferOffset);
|
||||
bufferOffset = 0UL;
|
||||
}
|
||||
|
||||
/* Copy remaining data in pbuf */
|
||||
(void)memcpy((uint8_t *) & (((uint8_t *)q->payload)[payloadOffset]), (uint8_t *) & (rxBuffer[bufferOffset]), byteCnt);
|
||||
(void)memcpy((uint8_t*)&(((uint8_t*)q->payload)[payloadOffset]), (uint8_t*)&(rxBuffer[bufferOffset]), byteCnt);
|
||||
bufferOffset = bufferOffset + byteCnt;
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +262,7 @@ struct pbuf *low_level_input(struct netif *netif)
|
|||
DmaRxDesc = (EthHandle.stcRxFrame).pstcFSDesc;
|
||||
for (i = 0UL; i < (EthHandle.stcRxFrame).u32SegCount; i++) {
|
||||
DmaRxDesc->u32ControlStatus |= ETH_DMA_RXDESC_OWN;
|
||||
DmaRxDesc = (stc_eth_dma_desc_t *)(DmaRxDesc->u32Buf2NextDescAddr);
|
||||
DmaRxDesc = (stc_eth_dma_desc_t*)(DmaRxDesc->u32Buf2NextDescAddr);
|
||||
}
|
||||
/* Clear Segment_Count */
|
||||
(EthHandle.stcRxFrame).u32SegCount = 0UL;
|
||||
|
@ -277,11 +278,10 @@ struct pbuf *low_level_input(struct netif *netif)
|
|||
return p;
|
||||
}
|
||||
|
||||
extern void LwipSetIPTest(int argc, char *argv[]);
|
||||
int HwEthInit(void) {
|
||||
// lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
LwipSetIPTest(1, NULL);
|
||||
return EOK;
|
||||
extern void LwipSetIPTest(int argc, char* argv[]);
|
||||
int HwEthInit(void)
|
||||
{
|
||||
// lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||
LwipSetIPTest(1, NULL);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eth_netdev.c
|
||||
* @brief register net dev function for lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023-08-07
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <inet.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netdev.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
static const uint32_t NETIF_NAME_LEN = 2;
|
||||
|
||||
static int lwip_netdev_set_up(struct netdev* netdev)
|
||||
{
|
||||
netif_set_up((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static int lwip_netdev_set_down(struct netdev* netif)
|
||||
{
|
||||
netif_set_down((struct netif*)netif->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef ip_2_ip4
|
||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
||||
#endif
|
||||
static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw)
|
||||
{
|
||||
if (ip_addr && netmask && gw) {
|
||||
netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
|
||||
} else {
|
||||
if (ip_addr) {
|
||||
netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr));
|
||||
}
|
||||
if (netmask) {
|
||||
netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask));
|
||||
}
|
||||
if (gw) {
|
||||
netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_DNS
|
||||
static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
|
||||
extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver);
|
||||
#else /* >=2.x */
|
||||
extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server);
|
||||
#endif /* LWIP_VERSION_MAJOR == 1U */
|
||||
|
||||
dns_setserver(dns_num, dns_server);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DHCP
|
||||
static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled)
|
||||
{
|
||||
netdev_low_level_set_dhcp_status(netdev, is_enabled);
|
||||
|
||||
if (true == is_enabled) {
|
||||
dhcp_start((struct netif*)netdev->user_data);
|
||||
} else {
|
||||
dhcp_stop((struct netif*)netdev->user_data);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lwip_netdev_set_default(struct netdev* netdev)
|
||||
{
|
||||
netif_set_default((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static const struct netdev_ops lwip_netdev_ops = {
|
||||
.set_up = lwip_netdev_set_up,
|
||||
.set_down = lwip_netdev_set_down,
|
||||
.set_addr_info = lwip_netdev_set_addr_info,
|
||||
#ifdef LWIP_DNS
|
||||
.set_dns_server = lwip_netdev_set_dns_server,
|
||||
#endif
|
||||
#ifdef LWIP_DHCP
|
||||
.set_dhcp = lwip_netdev_set_dhcp,
|
||||
#endif
|
||||
.set_default = lwip_netdev_set_default,
|
||||
};
|
||||
|
||||
static inline int netdev_set_flags(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
struct netdev* netdev = netdev_get_by_name(lwip_netif->name);
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
netdev->mtu = lwip_netif->mtu;
|
||||
// set flags
|
||||
if (lwip_netif->flags | NETIF_FLAG_BROADCAST) {
|
||||
netdev->flags |= NETDEV_FLAG_BROADCAST;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_ETHARP) {
|
||||
netdev->flags |= NETDEV_FLAG_ETHARP;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_IGMP) {
|
||||
netdev->flags |= NETDEV_FLAG_IGMP;
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
|
||||
if (lwip_netif->flags & NETIF_FLAG_MLD6) {
|
||||
netdev->flags |= NETDEV_FLAG_MLD6;
|
||||
}
|
||||
#endif /* LWIP_VERSION_MAJOR >= 2U */
|
||||
|
||||
#if LWIP_DHCP
|
||||
netdev_low_level_set_dhcp_status(netdev, true);
|
||||
#else
|
||||
netdev_low_level_set_dhcp_status(netdev, false);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
|
||||
struct netdev* netdev = calloc(1, sizeof(struct netdev));
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
// init netdev
|
||||
char netif_name[NETIF_NAME_LEN + 1];
|
||||
strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
// register netdev
|
||||
int result = netdev_register(netdev, netif_name, (void*)lwip_netif);
|
||||
// set values of netdev
|
||||
netdev_set_flags(lwip_netif);
|
||||
netdev->ops = &lwip_netdev_ops;
|
||||
netdev->hwaddr_len = lwip_netif->hwaddr_len;
|
||||
memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
|
||||
netdev->ip_addr = lwip_netif->ip_addr;
|
||||
netdev->gw = lwip_netif->gw;
|
||||
netdev->netmask = lwip_netif->netmask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lwip_netdev_del(struct netif* lwip_netif)
|
||||
{
|
||||
char name[NETIF_NAME_LEN + 1];
|
||||
struct netdev* netdev;
|
||||
|
||||
CHECK(lwip_netif);
|
||||
|
||||
strncpy(name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
netdev = netdev_get_by_name(name);
|
||||
netdev_unregister(netdev);
|
||||
free(netdev);
|
||||
}
|
|
@ -19,21 +19,21 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file ethernetif.c
|
||||
* @brief support edu-arm32-board ethernetif function and register to Lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
* @file ethernetif.c
|
||||
* @brief support hc32f4a0-board ethernetif function and register to Lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: ethernetif.c
|
||||
Description: support edu-arm32-board ethernetif configure and register to Lwip
|
||||
Others: take projects\ev_hc32f4a0_lqfp176\examples\eth\eth_loopback\source\ethernetif.c for references
|
||||
History:
|
||||
History:
|
||||
1. Date: 2022-12-05
|
||||
Author: AIIT XUOS Lab
|
||||
Modification:
|
||||
Modification:
|
||||
1、include harware_ethernetif.h、hc32_ll_eth.h、hc32_ll_gpio.h、hc32_ll_utility.h、hc32_ll_fcg.h and lwip H files;
|
||||
2、modify ethernetif_init as err_t;
|
||||
3、add ETH_RST_PORT and ETH_RST_PIN;
|
||||
|
@ -47,13 +47,15 @@ Modification:
|
|||
* Include files
|
||||
******************************************************************************/
|
||||
#include <connect_ethernet.h>
|
||||
#include <hc32_ll_fcg.h>
|
||||
#include <hc32_ll_gpio.h>
|
||||
#include <hc32_ll_utility.h>
|
||||
#include <hc32_ll_fcg.h>
|
||||
#include <lwip/timeouts.h>
|
||||
#include <netif/etharp.h>
|
||||
|
||||
#include <netdev.h>
|
||||
#include <xs_isr.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
/**
|
||||
* @addtogroup HC32F4A0_DDL_Examples
|
||||
|
@ -73,7 +75,6 @@ Modification:
|
|||
* Local pre-processor symbols/macros ('#define')
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Global variable definitions (declared in header file with 'extern')
|
||||
******************************************************************************/
|
||||
|
@ -86,7 +87,6 @@ Modification:
|
|||
* Local variable definitions ('static')
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function implementation - global ('extern') and local ('static')
|
||||
******************************************************************************/
|
||||
|
@ -180,41 +180,14 @@ void Ethernet_GpioInit(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void *ethernetif_config_enet_set(uint8_t enet_port) {
|
||||
void* ethernetif_config_enet_set(uint8_t enet_port)
|
||||
{
|
||||
return NONE;
|
||||
}
|
||||
|
||||
void Time_Update_LwIP(void) {
|
||||
//no need to do
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Should be called at the beginning of the program to set up the network interface.
|
||||
* @param netif The network interface structure for this ethernetif.
|
||||
* @retval err_t:
|
||||
* - LL_OK: The IF is initialized
|
||||
* - LL_ERR: The IF is uninitialized
|
||||
*/
|
||||
err_t ethernetif_init(struct netif *netif)
|
||||
void Time_Update_LwIP(void)
|
||||
{
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwip";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
|
||||
#ifndef ETHERNET_LOOPBACK_TEST
|
||||
/* We directly use etharp_output() here to save a function call.
|
||||
* You can instead declare your own function an call etharp_output()
|
||||
* from it if you have to do some checks before sending (e.g. if link
|
||||
* is available...) */
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
#endif
|
||||
|
||||
/* initialize the hardware */
|
||||
return low_level_init(netif);
|
||||
// no need to do
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,16 +195,16 @@ err_t ethernetif_init(struct netif *netif)
|
|||
* @param netif The network interface structure for this ethernetif.
|
||||
* @retval None
|
||||
*/
|
||||
void ethernetif_input(void *netif_arg)
|
||||
void ethernetif_input(void* netif_arg)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct netif *netif = (struct netif *)netif_arg;
|
||||
struct pbuf* p;
|
||||
struct netif* netif = (struct netif*)netif_arg;
|
||||
x_base critical_lock;
|
||||
|
||||
/* Move received packet into a new pbuf */
|
||||
while (1) {
|
||||
sys_arch_sem_wait(get_eth_recv_sem(), WAITING_FOREVER);
|
||||
while(1) {
|
||||
while (1) {
|
||||
p = low_level_input(netif);
|
||||
#ifndef ETHERNET_LOOPBACK_TEST
|
||||
/* Entry point to the LwIP stack */
|
||||
|
@ -256,12 +229,51 @@ void ethernetif_input(void *netif_arg)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Should be called at the beginning of the program to set up the network interface.
|
||||
* @param netif The network interface structure for this ethernetif.
|
||||
* @retval err_t:
|
||||
* - LL_OK: The IF is initialized
|
||||
* - LL_ERR: The IF is uninitialized
|
||||
*/
|
||||
err_t ethernetif_init(struct netif* netif)
|
||||
{
|
||||
#if LWIP_NETIF_HOSTNAME
|
||||
/* Initialize interface hostname */
|
||||
netif->hostname = "lwip";
|
||||
#endif /* LWIP_NETIF_HOSTNAME */
|
||||
netif->name[0] = IFNAME0;
|
||||
netif->name[1] = IFNAME1;
|
||||
|
||||
#ifndef ETHERNET_LOOPBACK_TEST
|
||||
/* We directly use etharp_output() here to save a function call.
|
||||
* You can instead declare your own function an call etharp_output()
|
||||
* from it if you have to do some checks before sending (e.g. if link
|
||||
* is available...) */
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = low_level_output;
|
||||
// netif->linkoutput = ethernetif_linkoutput;
|
||||
#endif
|
||||
|
||||
/* initialize the hardware */
|
||||
if (LL_OK != low_level_init(netif)) {
|
||||
return LL_ERR;
|
||||
}
|
||||
|
||||
if (EOK != lwip_netdev_add(netif)) {
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||
} else {
|
||||
// printf("[%s] Add Netdev successful\n", __func__);
|
||||
}
|
||||
return LL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check the netif link status.
|
||||
* @param netif the network interface
|
||||
* @retval None
|
||||
*/
|
||||
void EthernetIF_CheckLink(struct netif *netif)
|
||||
void EthernetIF_CheckLink(struct netif* netif)
|
||||
{
|
||||
uint16_t u16RegVal = 0U;
|
||||
static uint8_t u8PreStatus = 0U;
|
||||
|
@ -296,7 +308,7 @@ void EthernetIF_CheckLink(struct netif *netif)
|
|||
* @param netif The network interface.
|
||||
* @retval None
|
||||
*/
|
||||
void EthernetIF_UpdateLink(struct netif *netif)
|
||||
void EthernetIF_UpdateLink(struct netif* netif)
|
||||
{
|
||||
uint16_t u16RegVal;
|
||||
|
||||
|
@ -337,7 +349,7 @@ void EthernetIF_UpdateLink(struct netif *netif)
|
|||
* @param netif The network interface
|
||||
* @retval None
|
||||
*/
|
||||
void EthernetIF_PeriodicHandle(struct netif *netif)
|
||||
void EthernetIF_PeriodicHandle(struct netif* netif)
|
||||
{
|
||||
#ifndef ETH_INTERFACE_RMII
|
||||
uint32_t curTick;
|
||||
|
@ -358,7 +370,7 @@ void EthernetIF_PeriodicHandle(struct netif *netif)
|
|||
* @param netif The network interface
|
||||
* @retval None
|
||||
*/
|
||||
void EthernetIF_LinkCallback(struct netif *netif)
|
||||
void EthernetIF_LinkCallback(struct netif* netif)
|
||||
{
|
||||
__IO uint32_t tickStart = 0UL;
|
||||
uint16_t u16RegVal = 0U;
|
||||
|
@ -405,8 +417,7 @@ void EthernetIF_LinkCallback(struct netif *netif)
|
|||
CLR_REG16_BIT(u16RegVal, PHY_FULLDUPLEX_100M);
|
||||
/* Set MAC Speed and Duplex Mode to PHY */
|
||||
(void)ETH_PHY_WriteReg(&EthHandle, PHY_BCR,
|
||||
((uint16_t)((EthHandle.stcCommInit).u32DuplexMode >> 3U) |
|
||||
(uint16_t)((EthHandle.stcCommInit).u32Speed >> 1U) | u16RegVal));
|
||||
((uint16_t)((EthHandle.stcCommInit).u32DuplexMode >> 3U) | (uint16_t)((EthHandle.stcCommInit).u32Speed >> 1U) | u16RegVal));
|
||||
}
|
||||
/* ETH MAC Re-Configuration */
|
||||
ETH_MAC_SetDuplexSpeed((EthHandle.stcCommInit).u32DuplexMode, (EthHandle.stcCommInit).u32Speed);
|
||||
|
@ -427,7 +438,7 @@ void EthernetIF_LinkCallback(struct netif *netif)
|
|||
* - LL_OK: The IF is link up
|
||||
* - LL_ERR: The IF is link down
|
||||
*/
|
||||
int32_t EthernetIF_IsLinkUp(struct netif *netif)
|
||||
int32_t EthernetIF_IsLinkUp(struct netif* netif)
|
||||
{
|
||||
return (0U != u8PhyLinkStatus) ? LL_OK : LL_ERR;
|
||||
}
|
||||
|
@ -437,14 +448,14 @@ int32_t EthernetIF_IsLinkUp(struct netif *netif)
|
|||
* @param netif The network interface
|
||||
* @retval None
|
||||
*/
|
||||
__WEAKDEF void EthernetIF_NotifyLinkChange(struct netif *netif)
|
||||
__WEAKDEF void EthernetIF_NotifyLinkChange(struct netif* netif)
|
||||
{
|
||||
/* This is function could be implemented in user file when the callback is needed */
|
||||
if (LL_OK == EthernetIF_IsLinkUp(netif)) {
|
||||
GPIO_SetPins(ETH_LINK_LED_PORT, ETH_LINK_LED_PIN);
|
||||
} else {
|
||||
GPIO_ResetPins(ETH_LINK_LED_PORT, ETH_LINK_LED_PIN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -453,7 +464,8 @@ __WEAKDEF void EthernetIF_NotifyLinkChange(struct netif *netif)
|
|||
* @param p The MAC packet to receive
|
||||
* @retval None
|
||||
*/
|
||||
__WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p) {
|
||||
__WEAKDEF void EthernetIF_InputCallback(struct netif* netif, struct pbuf* p)
|
||||
{
|
||||
/* This is function could be implemented in user file when the callback is needed */
|
||||
#ifdef ETHERNET_LOOPBACK_TEST
|
||||
if ((0 == (memcmp(p->payload, txPbuf.payload, p->len))) && (p->len == txPbuf.len)) {
|
||||
|
@ -479,7 +491,7 @@ __WEAKDEF void EthernetIF_InputCallback(struct netif *netif, struct pbuf *p) {
|
|||
|
||||
#ifdef ETHERNET_LOOPBACK_TEST
|
||||
|
||||
static void EthLoopBackTask(void *parameter)
|
||||
static void EthLoopBackTask(void* parameter)
|
||||
{
|
||||
while (1) {
|
||||
if (RESET == GPIO_ReadInputPins(USER_KEY_PORT, USER_KEY_PIN)) {
|
||||
|
@ -489,7 +501,7 @@ static void EthLoopBackTask(void *parameter)
|
|||
}
|
||||
}
|
||||
|
||||
//KPrintf("ready to receive eth loop back data\n");
|
||||
// KPrintf("ready to receive eth loop back data\n");
|
||||
/* Read a received packet */
|
||||
ethernetif_input(&testnetif);
|
||||
/* Handle periodic timers */
|
||||
|
@ -514,24 +526,24 @@ static void EthLoopBackTest(void)
|
|||
(void)ethernetif_init(&testnetif);
|
||||
|
||||
/* fill data to txPbuf */
|
||||
txPbuf.next = NULL;
|
||||
txPbuf.next = NULL;
|
||||
txPbuf.payload = txBuf;
|
||||
txPbuf.len = strlen(txBuf);
|
||||
txPbuf.len = strlen(txBuf);
|
||||
|
||||
int eth_loopback_task = 0;
|
||||
eth_loopback_task = KTaskCreate("eth_loopback", EthLoopBackTask, NONE,
|
||||
2048, 8);
|
||||
if(eth_loopback_task < 0) {
|
||||
KPrintf("eth_loopback_task create failed ...%s %d.\n", __FUNCTION__,__LINE__);
|
||||
return;
|
||||
}
|
||||
2048, 8);
|
||||
if (eth_loopback_task < 0) {
|
||||
KPrintf("eth_loopback_task create failed ...%s %d.\n", __FUNCTION__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
StartupKTask(eth_loopback_task);
|
||||
|
||||
return;
|
||||
}
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
EthLoopBackTest, EthLoopBackTest, EthLoopBackTest);
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
|
||||
EthLoopBackTest, EthLoopBackTest, EthLoopBackTest);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -117,6 +117,9 @@ static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info
|
|||
|
||||
static uint32 I2cMasterWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
|
||||
{
|
||||
if (msg->len == 0) {
|
||||
return EOK;
|
||||
}
|
||||
uint32 i32Ret;
|
||||
|
||||
I2C_Cmd(I2C_UNIT, ENABLE);
|
||||
|
@ -171,6 +174,9 @@ static uint32 I2cMasterReadData(struct I2cHardwareDevice *i2c_dev, struct I2cDat
|
|||
}
|
||||
|
||||
static uint32 I2cSlaveWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) {
|
||||
if (msg->len == 0) {
|
||||
return EOK;
|
||||
}
|
||||
uint32 i32Ret;
|
||||
|
||||
I2C_Cmd(I2C_UNIT, ENABLE);
|
||||
|
@ -222,7 +228,7 @@ static uint32 I2cSlaveReadData(struct I2cHardwareDevice *i2c_dev, struct I2cData
|
|||
if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) {
|
||||
/* Slave receive data*/
|
||||
i32Ret = I2C_ReceiveData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
|
||||
KPrintf("Slave receive success!\r\n");
|
||||
KPrintf("Slave receive success!\r\n");
|
||||
|
||||
if ((LL_OK == i32Ret) || (LL_ERR_TIMEOUT == i32Ret)) {
|
||||
/* Wait stop condition */
|
||||
|
@ -336,7 +342,7 @@ int HwI2cInit(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
//#define I2C_TEST
|
||||
// #define I2C_TEST
|
||||
#ifdef I2C_TEST
|
||||
|
||||
#define USER_KEY_PORT (GPIO_PORT_I)
|
||||
|
|
|
@ -34,13 +34,6 @@ struct HwDac
|
|||
uint16 digital_data;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
CM_DAC_TypeDef *pUnit;
|
||||
// en_dac_cvt_t enCvtType;
|
||||
uint16_t u16Ch;
|
||||
} stc_dac_handle_t;
|
||||
|
||||
|
||||
int HwDacInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1,40 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_ethernet.h
|
||||
* @brief Adapted network software protocol stack and hardware operation functions
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
* @file connect_ethernet.h
|
||||
* @brief Adapted network software protocol stack and hardware operation functions
|
||||
* @version 2.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2022-12-05
|
||||
*/
|
||||
|
||||
#ifndef CONNECT_ETHERNET_H
|
||||
#define CONNECT_ETHERNET_H
|
||||
|
||||
#include "hardware_ethernetif.h"
|
||||
#include <sys_arch.h>
|
||||
#include <hc32_ll_eth.h>
|
||||
#include <hardware_irq.h>
|
||||
#include <hc32_ll_eth.h>
|
||||
#include <sys_arch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct hc32_irq_config
|
||||
{
|
||||
IRQn_Type irq_num;
|
||||
uint32_t irq_prio;
|
||||
en_int_src_t int_src;
|
||||
struct hc32_irq_config {
|
||||
IRQn_Type irq_num;
|
||||
uint32_t irq_prio;
|
||||
en_int_src_t int_src;
|
||||
};
|
||||
|
||||
/* Global Ethernet handle*/
|
||||
|
@ -52,22 +51,23 @@ __ALIGN_BEGIN static uint8_t EthRxBuff[ETH_RX_BUF_NUM][ETH_RX_BUF_SIZE];
|
|||
static uint8_t u8PhyLinkStatus = 0U, u8EthInitStatus = 0U;
|
||||
|
||||
static struct Hc32IrqConfig eth_irq_config = {
|
||||
.irq_num = BSP_ETH_IRQ_NUM,
|
||||
.irq_prio = BSP_ETH_IRQ_PRIO,
|
||||
.int_src = INT_SRC_ETH_GLB_INT,
|
||||
.irq_num = BSP_ETH_IRQ_NUM,
|
||||
.irq_prio = BSP_ETH_IRQ_PRIO,
|
||||
.int_src = INT_SRC_ETH_GLB_INT,
|
||||
};
|
||||
|
||||
void Ethernet_GpioInit(void);
|
||||
int32_t low_level_init(struct netif *netif);
|
||||
err_t low_level_output(struct netif *netif, struct pbuf *p);
|
||||
struct pbuf *low_level_input(struct netif *netif);
|
||||
int32_t low_level_init(struct netif* netif);
|
||||
err_t low_level_output(struct netif* netif, struct pbuf* p);
|
||||
struct pbuf* low_level_input(struct netif* netif);
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
int HwEthInit(void);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -13,6 +13,21 @@ menuconfig BSP_USING_UART3
|
|||
default "usart3_dev3"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_UART4
|
||||
bool "Enable USART4 for RS485"
|
||||
default y
|
||||
if BSP_USING_UART4
|
||||
config SERIAL_BUS_NAME_4
|
||||
string "serial bus 4 name"
|
||||
default "usart4"
|
||||
config SERIAL_DRV_NAME_4
|
||||
string "serial bus 4 driver name"
|
||||
default "usart4_drv"
|
||||
config SERIAL_4_DEVICE_NAME_0
|
||||
string "serial bus 4 device 0 name"
|
||||
default "usart4_dev4"
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_UART6
|
||||
bool "Enable USART6"
|
||||
default n
|
||||
|
|
|
@ -50,6 +50,14 @@ Modification:
|
|||
#define USART3_TX_PIN (GPIO_PIN_10)
|
||||
#endif
|
||||
|
||||
#if defined(BSP_USING_UART4)
|
||||
#define USART4_RX_PORT (GPIO_PORT_E)
|
||||
#define USART4_RX_PIN (GPIO_PIN_07)
|
||||
|
||||
#define USART4_TX_PORT (GPIO_PORT_G)
|
||||
#define USART4_TX_PIN (GPIO_PIN_00)
|
||||
#endif
|
||||
|
||||
#if defined(BSP_USING_UART6)
|
||||
#define USART6_RX_PORT (GPIO_PORT_H)
|
||||
#define USART6_RX_PIN (GPIO_PIN_06)
|
||||
|
@ -72,6 +80,12 @@ static x_err_t UartGpioInit(CM_USART_TypeDef *USARTx)
|
|||
GPIO_SetFunc(USART3_TX_PORT, USART3_TX_PIN, GPIO_FUNC_32);
|
||||
break;
|
||||
#endif
|
||||
#ifdef BSP_USING_UART4
|
||||
case (uint32)CM_USART4:
|
||||
GPIO_SetFunc(USART4_RX_PORT, USART4_RX_PIN, GPIO_FUNC_33);
|
||||
GPIO_SetFunc(USART4_TX_PORT, USART4_TX_PIN, GPIO_FUNC_32);
|
||||
break;
|
||||
#endif
|
||||
#ifdef BSP_USING_UART6
|
||||
case (uint32)CM_USART6:
|
||||
GPIO_SetFunc(USART6_RX_PORT, USART6_RX_PIN, GPIO_FUNC_37);
|
||||
|
@ -123,6 +137,32 @@ void Uart3RxErrIrqHandler(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART4
|
||||
struct SerialBus serial_bus_4;
|
||||
struct SerialDriver serial_driver_4;
|
||||
struct SerialHardwareDevice serial_device_4;
|
||||
|
||||
void Uart4RxIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
SerialSetIsr(&serial_device_4, SERIAL_EVENT_RX_IND);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
|
||||
void Uart4RxErrIrqHandler(void)
|
||||
{
|
||||
x_base lock = 0;
|
||||
lock = DISABLE_INTERRUPT();
|
||||
|
||||
UartRxErrIsr(&serial_bus_4, &serial_driver_4, &serial_device_4);
|
||||
|
||||
ENABLE_INTERRUPT(lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART6
|
||||
struct SerialBus serial_bus_6;
|
||||
struct SerialDriver serial_driver_6;
|
||||
|
@ -499,6 +539,57 @@ int HwUsartInit(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART4
|
||||
static struct SerialCfgParam serial_cfg_4;
|
||||
memset(&serial_cfg_4, 0, sizeof(struct SerialCfgParam));
|
||||
|
||||
static struct SerialDevParam serial_dev_param_4;
|
||||
memset(&serial_dev_param_4, 0, sizeof(struct SerialDevParam));
|
||||
|
||||
static struct UsartHwCfg serial_hw_cfg_4;
|
||||
memset(&serial_hw_cfg_4, 0, sizeof(struct UsartHwCfg));
|
||||
|
||||
serial_driver_4.drv_done = &drv_done;
|
||||
serial_driver_4.configure = SerialDrvConfigure;
|
||||
serial_device_4.hwdev_done = &hwdev_done;
|
||||
|
||||
serial_cfg_4.data_cfg = data_cfg_init;
|
||||
|
||||
//default irq configure
|
||||
serial_hw_cfg_4.uart_device = CM_USART4;
|
||||
serial_hw_cfg_4.usart_clock = FCG3_PERIPH_USART4;
|
||||
serial_hw_cfg_4.rx_err_irq.irq_config.irq_num = BSP_UART4_RXERR_IRQ_NUM;
|
||||
serial_hw_cfg_4.rx_err_irq.irq_config.irq_prio = BSP_UART4_RXERR_IRQ_PRIO;
|
||||
serial_hw_cfg_4.rx_err_irq.irq_config.int_src = INT_SRC_USART4_EI;
|
||||
|
||||
serial_hw_cfg_4.rx_irq.irq_config.irq_num = BSP_UART4_RX_IRQ_NUM;
|
||||
serial_hw_cfg_4.rx_irq.irq_config.irq_prio = BSP_UART4_RX_IRQ_PRIO;
|
||||
serial_hw_cfg_4.rx_irq.irq_config.int_src = INT_SRC_USART4_RI;
|
||||
|
||||
serial_hw_cfg_4.rx_err_irq.irq_callback = Uart4RxErrIrqHandler;
|
||||
serial_hw_cfg_4.rx_irq.irq_callback = Uart4RxIrqHandler;
|
||||
|
||||
hc32_install_irq_handler(&serial_hw_cfg_4.rx_err_irq.irq_config, serial_hw_cfg_4.rx_err_irq.irq_callback, 0);
|
||||
|
||||
serial_cfg_4.hw_cfg.private_data = (void *)&serial_hw_cfg_4;
|
||||
serial_driver_4.private_data = (void *)&serial_cfg_4;
|
||||
|
||||
serial_dev_param_4.serial_work_mode = SIGN_OPER_INT_RX;
|
||||
serial_device_4.haldev.private_data = (void *)&serial_dev_param_4;
|
||||
|
||||
ret = BoardSerialBusInit(&serial_bus_4, &serial_driver_4, SERIAL_BUS_NAME_4, SERIAL_DRV_NAME_4);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwUartInit uart4 error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = BoardSerialDevBend(&serial_device_4, (void *)&serial_cfg_4, SERIAL_BUS_NAME_4, SERIAL_4_DEVICE_NAME_0);
|
||||
if (EOK != ret) {
|
||||
KPrintf("HwUartInit uart4 error ret %u\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART6
|
||||
static struct SerialCfgParam serial_cfg_6;
|
||||
memset(&serial_cfg_6, 0, sizeof(struct SerialCfgParam));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c fsl_enet_qos.c
|
||||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c fsl_enet_qos.c eth_netdev.c
|
||||
SRC_DIR := phy mdio
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -353,5 +353,11 @@ err_t ethernetif_init(struct netif *netif,
|
|||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__));
|
||||
if (EOK != lwip_netdev_add(netif)) {
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||
} else {
|
||||
printf("[%s] Add Netdev successful\n", __func__);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eth_netdev.c
|
||||
* @brief register net dev function for lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023-08-07
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <inet.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netdev.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
static const uint32_t NETIF_NAME_LEN = 2;
|
||||
|
||||
static int lwip_netdev_set_up(struct netdev* netdev)
|
||||
{
|
||||
netif_set_up((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static int lwip_netdev_set_down(struct netdev* netif)
|
||||
{
|
||||
netif_set_down((struct netif*)netif->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef ip_2_ip4
|
||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
||||
#endif
|
||||
static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw)
|
||||
{
|
||||
if (ip_addr && netmask && gw) {
|
||||
netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
|
||||
} else {
|
||||
if (ip_addr) {
|
||||
netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr));
|
||||
}
|
||||
if (netmask) {
|
||||
netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask));
|
||||
}
|
||||
if (gw) {
|
||||
netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_DNS
|
||||
static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
|
||||
extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver);
|
||||
#else /* >=2.x */
|
||||
extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server);
|
||||
#endif /* LWIP_VERSION_MAJOR == 1U */
|
||||
|
||||
dns_setserver(dns_num, dns_server);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DHCP
|
||||
static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled)
|
||||
{
|
||||
netdev_low_level_set_dhcp_status(netdev, is_enabled);
|
||||
|
||||
if (true == is_enabled) {
|
||||
dhcp_start((struct netif*)netdev->user_data);
|
||||
} else {
|
||||
dhcp_stop((struct netif*)netdev->user_data);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lwip_netdev_set_default(struct netdev* netdev)
|
||||
{
|
||||
netif_set_default((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static const struct netdev_ops lwip_netdev_ops = {
|
||||
.set_up = lwip_netdev_set_up,
|
||||
.set_down = lwip_netdev_set_down,
|
||||
.set_addr_info = lwip_netdev_set_addr_info,
|
||||
#ifdef LWIP_DNS
|
||||
.set_dns_server = lwip_netdev_set_dns_server,
|
||||
#endif
|
||||
#ifdef LWIP_DHCP
|
||||
.set_dhcp = lwip_netdev_set_dhcp,
|
||||
#endif
|
||||
.set_default = lwip_netdev_set_default,
|
||||
};
|
||||
|
||||
static inline int netdev_set_flags(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
struct netdev* netdev = netdev_get_by_name(lwip_netif->name);
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
netdev->mtu = lwip_netif->mtu;
|
||||
// set flags
|
||||
if (lwip_netif->flags | NETIF_FLAG_BROADCAST) {
|
||||
netdev->flags |= NETDEV_FLAG_BROADCAST;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_ETHARP) {
|
||||
netdev->flags |= NETDEV_FLAG_ETHARP;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_IGMP) {
|
||||
netdev->flags |= NETDEV_FLAG_IGMP;
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
|
||||
if (lwip_netif->flags & NETIF_FLAG_MLD6) {
|
||||
netdev->flags |= NETDEV_FLAG_MLD6;
|
||||
}
|
||||
#endif /* LWIP_VERSION_MAJOR >= 2U */
|
||||
|
||||
#if LWIP_DHCP
|
||||
netdev_low_level_set_dhcp_status(netdev, true);
|
||||
#else
|
||||
netdev_low_level_set_dhcp_status(netdev, false);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
|
||||
struct netdev* netdev = calloc(1, sizeof(struct netdev));
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
// init netdev
|
||||
char netif_name[NETIF_NAME_LEN + 1];
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name));
|
||||
strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
// register netdev
|
||||
int result = netdev_register(netdev, netif_name, (void*)lwip_netif);
|
||||
// set values of netdev
|
||||
netdev_set_flags(lwip_netif);
|
||||
netdev->ops = &lwip_netdev_ops;
|
||||
netdev->hwaddr_len = lwip_netif->hwaddr_len;
|
||||
memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
|
||||
netdev->ip_addr = lwip_netif->ip_addr;
|
||||
netdev->gw = lwip_netif->gw;
|
||||
netdev->netmask = lwip_netif->netmask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lwip_netdev_del(struct netif* lwip_netif)
|
||||
{
|
||||
char name[NETIF_NAME_LEN + 1];
|
||||
struct netdev* netdev;
|
||||
|
||||
CHECK(lwip_netif);
|
||||
|
||||
strncpy(name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
netdev = netdev_get_by_name(name);
|
||||
netdev_unregister(netdev);
|
||||
free(netdev);
|
||||
}
|
|
@ -33,6 +33,8 @@
|
|||
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
|
||||
#endif
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -164,6 +164,9 @@ void ethernetif_input( void *netif_arg);
|
|||
int ETH_BSP_Config(void);
|
||||
void *ethernetif_config_enet_set(uint8_t enet_port);
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c
|
||||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c
|
||||
SRC_DIR := ksz8081
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -68,6 +68,7 @@
|
|||
#include "fsl_gpio.h"
|
||||
#include "fsl_iomuxc.h"
|
||||
|
||||
#include "netdev.h"
|
||||
#include "sys_arch.h"
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
|
|||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__));
|
||||
if (EOK != lwip_netdev_add(netif)) {
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||
} else {
|
||||
printf("[%s] Add Netdev successful\n", __func__);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eth_netdev.c
|
||||
* @brief register net dev function for lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023-08-07
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <inet.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netdev.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
static const uint32_t NETIF_NAME_LEN = 2;
|
||||
|
||||
static int lwip_netdev_set_up(struct netdev* netdev)
|
||||
{
|
||||
netif_set_up((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static int lwip_netdev_set_down(struct netdev* netif)
|
||||
{
|
||||
netif_set_down((struct netif*)netif->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef ip_2_ip4
|
||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
||||
#endif
|
||||
static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw)
|
||||
{
|
||||
if (ip_addr && netmask && gw) {
|
||||
netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
|
||||
} else {
|
||||
if (ip_addr) {
|
||||
netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr));
|
||||
}
|
||||
if (netmask) {
|
||||
netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask));
|
||||
}
|
||||
if (gw) {
|
||||
netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_DNS
|
||||
static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
|
||||
extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver);
|
||||
#else /* >=2.x */
|
||||
extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server);
|
||||
#endif /* LWIP_VERSION_MAJOR == 1U */
|
||||
|
||||
dns_setserver(dns_num, dns_server);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DHCP
|
||||
static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled)
|
||||
{
|
||||
netdev_low_level_set_dhcp_status(netdev, is_enabled);
|
||||
|
||||
if (true == is_enabled) {
|
||||
dhcp_start((struct netif*)netdev->user_data);
|
||||
} else {
|
||||
dhcp_stop((struct netif*)netdev->user_data);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lwip_netdev_set_default(struct netdev* netdev)
|
||||
{
|
||||
netif_set_default((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static const struct netdev_ops lwip_netdev_ops = {
|
||||
.set_up = lwip_netdev_set_up,
|
||||
.set_down = lwip_netdev_set_down,
|
||||
.set_addr_info = lwip_netdev_set_addr_info,
|
||||
#ifdef LWIP_DNS
|
||||
.set_dns_server = lwip_netdev_set_dns_server,
|
||||
#endif
|
||||
#ifdef LWIP_DHCP
|
||||
.set_dhcp = lwip_netdev_set_dhcp,
|
||||
#endif
|
||||
.set_default = lwip_netdev_set_default,
|
||||
};
|
||||
|
||||
static inline int netdev_set_flags(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
struct netdev* netdev = netdev_get_by_name(lwip_netif->name);
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
netdev->mtu = lwip_netif->mtu;
|
||||
// set flags
|
||||
if (lwip_netif->flags | NETIF_FLAG_BROADCAST) {
|
||||
netdev->flags |= NETDEV_FLAG_BROADCAST;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_ETHARP) {
|
||||
netdev->flags |= NETDEV_FLAG_ETHARP;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_IGMP) {
|
||||
netdev->flags |= NETDEV_FLAG_IGMP;
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
|
||||
if (lwip_netif->flags & NETIF_FLAG_MLD6) {
|
||||
netdev->flags |= NETDEV_FLAG_MLD6;
|
||||
}
|
||||
#endif /* LWIP_VERSION_MAJOR >= 2U */
|
||||
|
||||
#if LWIP_DHCP
|
||||
netdev_low_level_set_dhcp_status(netdev, true);
|
||||
#else
|
||||
netdev_low_level_set_dhcp_status(netdev, false);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
|
||||
struct netdev* netdev = calloc(1, sizeof(struct netdev));
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
// init netdev
|
||||
char netif_name[NETIF_NAME_LEN + 1];
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name));
|
||||
strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
// register netdev
|
||||
int result = netdev_register(netdev, netif_name, (void*)lwip_netif);
|
||||
// set values of netdev
|
||||
netdev_set_flags(lwip_netif);
|
||||
netdev->ops = &lwip_netdev_ops;
|
||||
netdev->hwaddr_len = lwip_netif->hwaddr_len;
|
||||
memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
|
||||
netdev->ip_addr = lwip_netif->ip_addr;
|
||||
netdev->gw = lwip_netif->gw;
|
||||
netdev->netmask = lwip_netif->netmask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lwip_netdev_del(struct netif* lwip_netif)
|
||||
{
|
||||
char name[NETIF_NAME_LEN + 1];
|
||||
struct netdev* netdev;
|
||||
|
||||
CHECK(lwip_netif);
|
||||
|
||||
strncpy(name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
netdev = netdev_get_by_name(name);
|
||||
netdev_unregister(netdev);
|
||||
free(netdev);
|
||||
}
|
|
@ -33,6 +33,8 @@
|
|||
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
|
||||
#endif
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -181,11 +181,14 @@ err_t ethernetif1_init(struct netif *netif);
|
|||
*/
|
||||
void ethernetif_input( void *netif_arg);
|
||||
|
||||
void ETH_BSP_Config(void);
|
||||
int ETH_BSP_Config(void);
|
||||
void *ethernetif_config_enet_set(uint8_t enet_port);
|
||||
|
||||
int32 lwip_obtain_semaphore(struct netif *netif);
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#define NETIF_ENET0_INIT_FUNC ethernetif0_init
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c
|
||||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c
|
||||
SRC_DIR := lan8720
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -68,6 +68,7 @@
|
|||
#include "fsl_gpio.h"
|
||||
#include "fsl_iomuxc.h"
|
||||
|
||||
#include "netdev.h"
|
||||
#include "sys_arch.h"
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
|
|||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__));
|
||||
if (EOK != lwip_netdev_add(netif)) {
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||
} else {
|
||||
printf("[%s] Add Netdev successful\n", __func__);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eth_netdev.c
|
||||
* @brief register net dev function for lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023-08-07
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <inet.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netdev.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
static const uint32_t NETIF_NAME_LEN = 2;
|
||||
|
||||
static int lwip_netdev_set_up(struct netdev* netdev)
|
||||
{
|
||||
netif_set_up((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static int lwip_netdev_set_down(struct netdev* netif)
|
||||
{
|
||||
netif_set_down((struct netif*)netif->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef ip_2_ip4
|
||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
||||
#endif
|
||||
static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw)
|
||||
{
|
||||
if (ip_addr && netmask && gw) {
|
||||
netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
|
||||
} else {
|
||||
if (ip_addr) {
|
||||
netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr));
|
||||
}
|
||||
if (netmask) {
|
||||
netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask));
|
||||
}
|
||||
if (gw) {
|
||||
netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_DNS
|
||||
static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
|
||||
extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver);
|
||||
#else /* >=2.x */
|
||||
extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server);
|
||||
#endif /* LWIP_VERSION_MAJOR == 1U */
|
||||
|
||||
dns_setserver(dns_num, dns_server);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DHCP
|
||||
static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled)
|
||||
{
|
||||
netdev_low_level_set_dhcp_status(netdev, is_enabled);
|
||||
|
||||
if (true == is_enabled) {
|
||||
dhcp_start((struct netif*)netdev->user_data);
|
||||
} else {
|
||||
dhcp_stop((struct netif*)netdev->user_data);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lwip_netdev_set_default(struct netdev* netdev)
|
||||
{
|
||||
netif_set_default((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static const struct netdev_ops lwip_netdev_ops = {
|
||||
.set_up = lwip_netdev_set_up,
|
||||
.set_down = lwip_netdev_set_down,
|
||||
.set_addr_info = lwip_netdev_set_addr_info,
|
||||
#ifdef LWIP_DNS
|
||||
.set_dns_server = lwip_netdev_set_dns_server,
|
||||
#endif
|
||||
#ifdef LWIP_DHCP
|
||||
.set_dhcp = lwip_netdev_set_dhcp,
|
||||
#endif
|
||||
.set_default = lwip_netdev_set_default,
|
||||
};
|
||||
|
||||
static inline int netdev_set_flags(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
struct netdev* netdev = netdev_get_by_name(lwip_netif->name);
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
netdev->mtu = lwip_netif->mtu;
|
||||
// set flags
|
||||
if (lwip_netif->flags | NETIF_FLAG_BROADCAST) {
|
||||
netdev->flags |= NETDEV_FLAG_BROADCAST;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_ETHARP) {
|
||||
netdev->flags |= NETDEV_FLAG_ETHARP;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_IGMP) {
|
||||
netdev->flags |= NETDEV_FLAG_IGMP;
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
|
||||
if (lwip_netif->flags & NETIF_FLAG_MLD6) {
|
||||
netdev->flags |= NETDEV_FLAG_MLD6;
|
||||
}
|
||||
#endif /* LWIP_VERSION_MAJOR >= 2U */
|
||||
|
||||
#if LWIP_DHCP
|
||||
netdev_low_level_set_dhcp_status(netdev, true);
|
||||
#else
|
||||
netdev_low_level_set_dhcp_status(netdev, false);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
|
||||
struct netdev* netdev = calloc(1, sizeof(struct netdev));
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
// init netdev
|
||||
char netif_name[NETIF_NAME_LEN + 1];
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name));
|
||||
strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
// register netdev
|
||||
int result = netdev_register(netdev, netif_name, (void*)lwip_netif);
|
||||
// set values of netdev
|
||||
netdev_set_flags(lwip_netif);
|
||||
netdev->ops = &lwip_netdev_ops;
|
||||
netdev->hwaddr_len = lwip_netif->hwaddr_len;
|
||||
memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
|
||||
netdev->ip_addr = lwip_netif->ip_addr;
|
||||
netdev->gw = lwip_netif->gw;
|
||||
netdev->netmask = lwip_netif->netmask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lwip_netdev_del(struct netif* lwip_netif)
|
||||
{
|
||||
char name[NETIF_NAME_LEN + 1];
|
||||
struct netdev* netdev;
|
||||
|
||||
CHECK(lwip_netif);
|
||||
|
||||
strncpy(name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
netdev = netdev_get_by_name(name);
|
||||
netdev_unregister(netdev);
|
||||
free(netdev);
|
||||
}
|
|
@ -33,6 +33,8 @@
|
|||
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
|
||||
#endif
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -185,6 +185,9 @@ int ETH_BSP_Config(void);
|
|||
void *ethernetif_config_enet_set(uint8_t enet_port);
|
||||
int32 lwip_obtain_semaphore(struct netif *netif);
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#define NETIF_ENET0_INIT_FUNC ethernetif0_init
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c
|
||||
SRC_FILES := enet_ethernetif.c enet_ethernetif_kinetis.c fsl_enet.c eth_netdev.c
|
||||
SRC_DIR := lan8720
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
|
@ -68,6 +68,7 @@
|
|||
#include "fsl_gpio.h"
|
||||
#include "fsl_iomuxc.h"
|
||||
|
||||
#include "netdev.h"
|
||||
#include "sys_arch.h"
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -319,6 +320,12 @@ err_t ethernetif_init(struct netif *netif, struct ethernetif *ethernetif,
|
|||
}
|
||||
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
|
||||
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Adding netdev.\n", __func__));
|
||||
if (EOK != lwip_netdev_add(netif)) {
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||
} else {
|
||||
printf("[%s] Add Netdev successful\n", __func__);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* Copyright (c) 2001-2004 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file eth_netdev.c
|
||||
* @brief register net dev function for lwip
|
||||
* @version 3.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2023-08-07
|
||||
*/
|
||||
|
||||
#include <connect_ethernet.h>
|
||||
#include <inet.h>
|
||||
#include <lwip/dhcp.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <netdev.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
static const uint32_t NETIF_NAME_LEN = 2;
|
||||
|
||||
static int lwip_netdev_set_up(struct netdev* netdev)
|
||||
{
|
||||
netif_set_up((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static int lwip_netdev_set_down(struct netdev* netif)
|
||||
{
|
||||
netif_set_down((struct netif*)netif->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#ifndef ip_2_ip4
|
||||
#define ip_2_ip4(ipaddr) (ipaddr)
|
||||
#endif
|
||||
static int lwip_netdev_set_addr_info(struct netdev* netdev, ip_addr_t* ip_addr, ip_addr_t* netmask, ip_addr_t* gw)
|
||||
{
|
||||
if (ip_addr && netmask && gw) {
|
||||
netif_set_addr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw));
|
||||
} else {
|
||||
if (ip_addr) {
|
||||
netif_set_ipaddr((struct netif*)netdev->user_data, ip_2_ip4(ip_addr));
|
||||
}
|
||||
if (netmask) {
|
||||
netif_set_netmask((struct netif*)netdev->user_data, ip_2_ip4(netmask));
|
||||
}
|
||||
if (gw) {
|
||||
netif_set_gw((struct netif*)netdev->user_data, ip_2_ip4(gw));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_DNS
|
||||
static int lwip_netdev_set_dns_server(struct netdev* netdev, uint8_t dns_num, ip_addr_t* dns_server)
|
||||
{
|
||||
#if LWIP_VERSION_MAJOR == 1U /* v1.x */
|
||||
extern void dns_setserver(u8_t numdns, ip_addr_t * dnsserver);
|
||||
#else /* >=2.x */
|
||||
extern void dns_setserver(uint8_t dns_num, const ip_addr_t* dns_server);
|
||||
#endif /* LWIP_VERSION_MAJOR == 1U */
|
||||
|
||||
dns_setserver(dns_num, dns_server);
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LWIP_DHCP
|
||||
static int lwip_netdev_set_dhcp(struct netdev* netdev, bool is_enabled)
|
||||
{
|
||||
netdev_low_level_set_dhcp_status(netdev, is_enabled);
|
||||
|
||||
if (true == is_enabled) {
|
||||
dhcp_start((struct netif*)netdev->user_data);
|
||||
} else {
|
||||
dhcp_stop((struct netif*)netdev->user_data);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lwip_netdev_set_default(struct netdev* netdev)
|
||||
{
|
||||
netif_set_default((struct netif*)netdev->user_data);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static const struct netdev_ops lwip_netdev_ops = {
|
||||
.set_up = lwip_netdev_set_up,
|
||||
.set_down = lwip_netdev_set_down,
|
||||
.set_addr_info = lwip_netdev_set_addr_info,
|
||||
#ifdef LWIP_DNS
|
||||
.set_dns_server = lwip_netdev_set_dns_server,
|
||||
#endif
|
||||
#ifdef LWIP_DHCP
|
||||
.set_dhcp = lwip_netdev_set_dhcp,
|
||||
#endif
|
||||
.set_default = lwip_netdev_set_default,
|
||||
};
|
||||
|
||||
static inline int netdev_set_flags(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
struct netdev* netdev = netdev_get_by_name(lwip_netif->name);
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
netdev->mtu = lwip_netif->mtu;
|
||||
// set flags
|
||||
if (lwip_netif->flags | NETIF_FLAG_BROADCAST) {
|
||||
netdev->flags |= NETDEV_FLAG_BROADCAST;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_ETHARP) {
|
||||
netdev->flags |= NETDEV_FLAG_ETHARP;
|
||||
}
|
||||
if (lwip_netif->flags | NETIF_FLAG_IGMP) {
|
||||
netdev->flags |= NETDEV_FLAG_IGMP;
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR >= 2U /* >= v2.x */
|
||||
if (lwip_netif->flags & NETIF_FLAG_MLD6) {
|
||||
netdev->flags |= NETDEV_FLAG_MLD6;
|
||||
}
|
||||
#endif /* LWIP_VERSION_MAJOR >= 2U */
|
||||
|
||||
#if LWIP_DHCP
|
||||
netdev_low_level_set_dhcp_status(netdev, true);
|
||||
#else
|
||||
netdev_low_level_set_dhcp_status(netdev, false);
|
||||
#endif
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif)
|
||||
{
|
||||
CHECK(lwip_netif);
|
||||
|
||||
struct netdev* netdev = calloc(1, sizeof(struct netdev));
|
||||
if (netdev == NULL) {
|
||||
return -ERR_IF;
|
||||
}
|
||||
|
||||
// init netdev
|
||||
char netif_name[NETIF_NAME_LEN + 1];
|
||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] Lwip netif name: %s\n", __func__, lwip_netif->name));
|
||||
strncpy(netif_name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
// register netdev
|
||||
int result = netdev_register(netdev, netif_name, (void*)lwip_netif);
|
||||
// set values of netdev
|
||||
netdev_set_flags(lwip_netif);
|
||||
netdev->ops = &lwip_netdev_ops;
|
||||
netdev->hwaddr_len = lwip_netif->hwaddr_len;
|
||||
memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len);
|
||||
netdev->ip_addr = lwip_netif->ip_addr;
|
||||
netdev->gw = lwip_netif->gw;
|
||||
netdev->netmask = lwip_netif->netmask;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lwip_netdev_del(struct netif* lwip_netif)
|
||||
{
|
||||
char name[NETIF_NAME_LEN + 1];
|
||||
struct netdev* netdev;
|
||||
|
||||
CHECK(lwip_netif);
|
||||
|
||||
strncpy(name, lwip_netif->name, NETIF_NAME_LEN);
|
||||
netdev = netdev_get_by_name(name);
|
||||
netdev_unregister(netdev);
|
||||
free(netdev);
|
||||
}
|
|
@ -1,22 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
* Copyright (c) 2021 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_ethernet.h
|
||||
* @brief Adapted network software protocol stack and hardware operation functions
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-12-7
|
||||
*/
|
||||
* @file connect_ethernet.h
|
||||
* @brief Adapted network software protocol stack and hardware operation functions
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-12-7
|
||||
*/
|
||||
|
||||
#ifndef __CONNECT_ETHERNET_H_
|
||||
#define __CONNECT_ETHERNET_H_
|
||||
|
@ -25,17 +25,18 @@
|
|||
#include "enet_ethernetif_priv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef sourceClock
|
||||
#define sourceClock CLOCK_GetFreq(kCLOCK_CoreSysClk)
|
||||
#endif
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -185,6 +185,9 @@ int ETH_BSP_Config(void);
|
|||
void *ethernetif_config_enet_set(uint8_t enet_port);
|
||||
int32 lwip_obtain_semaphore(struct netif *netif);
|
||||
|
||||
int lwip_netdev_add(struct netif* lwip_netif);
|
||||
void lwip_netdev_del(struct netif* lwip_netif);
|
||||
|
||||
#define NETIF_ENET0_INIT_FUNC ethernetif0_init
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -772,7 +772,8 @@ int stat(const char *path, struct stat *buf)
|
|||
|
||||
ret = mp->fs->stat(mp, relpath, &vfs_statbuf);
|
||||
if (ret < 0) {
|
||||
SYS_ERR("%s: stat file failed\n", __func__);
|
||||
// stat() is absolutely fine to check if a file exists
|
||||
// SYS_ERR("%s: stat file failed\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -790,7 +791,6 @@ err:
|
|||
free(abspath);
|
||||
|
||||
if (ret < 0) {
|
||||
KUpdateExstatus(ret);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
* Copyright (c) 2020 AIIT XUOS Lab
|
||||
* XiUOS is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file: xs_kdbg.h
|
||||
* @brief: function declaration and structure defintion of kernel debug
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/4/20
|
||||
*
|
||||
*/
|
||||
* @file: xs_kdbg.h
|
||||
* @brief: function declaration and structure defintion of kernel debug
|
||||
* @version: 1.0
|
||||
* @author: AIIT XUOS Lab
|
||||
* @date: 2020/4/20
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef XS_KDBG_H
|
||||
#define XS_KDBG_H
|
||||
|
@ -28,6 +28,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define KERNEL_DEBUG
|
||||
|
||||
#ifdef KERNEL_DEBUG
|
||||
|
||||
/*Kernel Section Debug Define*/
|
||||
|
@ -40,18 +42,22 @@ extern "C" {
|
|||
#define KDBG_IPC 0
|
||||
#define KDBG_HOOK 0
|
||||
|
||||
#define SYS_KDEBUG_LOG(section, information) \
|
||||
do \
|
||||
{ \
|
||||
if(section) { \
|
||||
KPrintf information; \
|
||||
} \
|
||||
}while (0)
|
||||
#define MSGQUEUE_DEBUG 0
|
||||
#define FILESYS_DEBUG 0
|
||||
#define NETDEV_DEBUG 0
|
||||
#define WEBNET_DEBUG 0
|
||||
|
||||
#define KDYN_NONE 0
|
||||
#define KDYN_DBG 1
|
||||
#define KDYN_ERROR 2
|
||||
#define KDYN_WARNING 3
|
||||
#define SYS_KDEBUG_LOG(section, information) \
|
||||
do { \
|
||||
if (section) { \
|
||||
KPrintf information; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define KDYN_NONE 0
|
||||
#define KDYN_DBG 1
|
||||
#define KDYN_ERROR 2
|
||||
#define KDYN_WARNING 3
|
||||
|
||||
#ifdef KDYN_LOG_DBG
|
||||
#define DBG(args, ...) KDYNAMIC_LOG(KDYN_DBG, args, ##__VA_ARGS__)
|
||||
|
@ -63,83 +69,76 @@ extern "C" {
|
|||
#define SYS_WARN(args, ...) KDYNAMIC_LOG(KDYN_WARNING, args, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define KDYNAMIC_LOG(level, args, ...) \
|
||||
do \
|
||||
{ \
|
||||
switch(level) \
|
||||
{ \
|
||||
case KDYN_NONE: \
|
||||
break; \
|
||||
case KDYN_DBG: \
|
||||
KPrintf("[DBG]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
case KDYN_ERROR: \
|
||||
KPrintf("[ERR]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
case KDYN_WARNING: \
|
||||
KPrintf("[WARN]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
}while (0)
|
||||
#define KDYNAMIC_LOG(level, args, ...) \
|
||||
do { \
|
||||
switch (level) { \
|
||||
case KDYN_NONE: \
|
||||
break; \
|
||||
case KDYN_DBG: \
|
||||
KPrintf("[DBG]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
case KDYN_ERROR: \
|
||||
KPrintf("[ERR]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
case KDYN_WARNING: \
|
||||
KPrintf("[WARN]"); \
|
||||
KPrintf(args, ##__VA_ARGS__); \
|
||||
break; \
|
||||
default: \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NULL_PARAM_CHECK(param) \
|
||||
do \
|
||||
{ \
|
||||
if(param == NONE) { \
|
||||
KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n",__FUNCTION__,__LINE__,#param); \
|
||||
while(RET_TRUE); \
|
||||
} \
|
||||
}while (0)
|
||||
#define NULL_PARAM_CHECK(param) \
|
||||
do { \
|
||||
if (param == NONE) { \
|
||||
KPrintf("PARAM CHECK FAILED ...%s %d %s is NULL.\n", __FUNCTION__, __LINE__, #param); \
|
||||
while (RET_TRUE) \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK(TRUE_CONDITION) \
|
||||
do \
|
||||
{ \
|
||||
if(!(TRUE_CONDITION)) { \
|
||||
KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n",#TRUE_CONDITION,__LINE__,__FUNCTION__);\
|
||||
while(RET_TRUE); \
|
||||
} \
|
||||
} while(0)
|
||||
#define CHECK(TRUE_CONDITION) \
|
||||
do { \
|
||||
if (!(TRUE_CONDITION)) { \
|
||||
KPrintf("%s CHECK condition is false at line[%d] of [%s] func.\n", #TRUE_CONDITION, __LINE__, __FUNCTION__); \
|
||||
while (RET_TRUE) \
|
||||
; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define KDEBUG_NOT_IN_INTERRUPT \
|
||||
do { \
|
||||
x_base level; \
|
||||
level = DISABLE_INTERRUPT(); \
|
||||
if (isrManager.done->getCounter() != 0) { \
|
||||
KPrintf("Function[%s] is not supported in ISR\n", __FUNCTION__); \
|
||||
CHECK(0); \
|
||||
} \
|
||||
ENABLE_INTERRUPT(level); \
|
||||
} while (0)
|
||||
|
||||
#define KDEBUG_NOT_IN_INTERRUPT \
|
||||
do \
|
||||
{ \
|
||||
x_base level; \
|
||||
level = DISABLE_INTERRUPT(); \
|
||||
if (isrManager.done->getCounter() != 0) \
|
||||
{ \
|
||||
KPrintf("Function[%s] is not supported in ISR\n", __FUNCTION__); \
|
||||
CHECK(0); \
|
||||
} \
|
||||
ENABLE_INTERRUPT(level); \
|
||||
} while (0)
|
||||
#define KDEBUG_IN_KTASK_CONTEXT \
|
||||
do { \
|
||||
x_base level; \
|
||||
level = DISABLE_INTERRUPT(); \
|
||||
if (GetKTaskDescriptor() == NONE) { \
|
||||
KPrintf("Function[%s] is not supported before task assign\n", __FUNCTION__); \
|
||||
CHECK(0); \
|
||||
} \
|
||||
KDEBUG_NOT_IN_INTERRUPT; \
|
||||
ENABLE_INTERRUPT(level); \
|
||||
} while (0)
|
||||
|
||||
#define KDEBUG_IN_KTASK_CONTEXT \
|
||||
do \
|
||||
{ \
|
||||
x_base level; \
|
||||
level = DISABLE_INTERRUPT(); \
|
||||
if (GetKTaskDescriptor() == NONE) \
|
||||
{ \
|
||||
KPrintf("Function[%s] is not supported before task assign\n", __FUNCTION__); \
|
||||
CHECK(0); \
|
||||
} \
|
||||
KDEBUG_NOT_IN_INTERRUPT; \
|
||||
ENABLE_INTERRUPT(level); \
|
||||
} while (0)
|
||||
|
||||
#define NOT_IN_CRITICAL_AREA \
|
||||
do { \
|
||||
if(GetOsAssignLockLevel() != 0){ \
|
||||
#define NOT_IN_CRITICAL_AREA \
|
||||
do { \
|
||||
if (GetOsAssignLockLevel() != 0) { \
|
||||
KPrintf("Function[%s] is not supported switch in critical area.\n", __FUNCTION__); \
|
||||
CHECK(0); \
|
||||
} \
|
||||
} while (0)
|
||||
CHECK(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
|
@ -159,4 +158,4 @@ extern "C" {
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#define ADDR 0x44 /* slave address */
|
||||
|
||||
static struct Bus *i2c_bus = NONE; /* I2C bus handle */
|
||||
static char addr = 0x44;
|
||||
|
||||
typedef struct Hs300xData
|
||||
{
|
||||
|
@ -50,6 +51,9 @@ static x_err_t WriteReg(struct HardwareDev *dev)
|
|||
{
|
||||
struct BusBlockWriteParam write_param;
|
||||
|
||||
write_param.buffer = &addr;
|
||||
write_param.size = 1;
|
||||
|
||||
/* use I2C device API transfer data */
|
||||
if(1 == BusDevWriteData(dev, &write_param)) {
|
||||
return EOK;
|
||||
|
|
|
@ -53,8 +53,10 @@
|
|||
#define ALLOC_BLOCK_MASK 0xc0000000
|
||||
#define DYNAMIC_REMAINING_MASK 0x3fffffff
|
||||
|
||||
#define SIZEOF_32B (32)
|
||||
#define SIZEOF_64B (64)
|
||||
enum SmallSizeAllocSize {
|
||||
SIZEOF_32B = 32,
|
||||
SIZEOF_64B = 64,
|
||||
};
|
||||
|
||||
#define SMALL_SIZE_32B(ITEMSIZE) ((ITEMSIZE + SIZEOF_DYNAMICALLOCNODE_MEM) * SMALL_NUMBER_32B) /* Calculate the total size for SIZEOF_32B blocks*/
|
||||
#define SMALL_SIZE_64B(ITEMSIZE) ((ITEMSIZE + SIZEOF_DYNAMICALLOCNODE_MEM) * SMALL_NUMBER_64B) /* Calculate the total size for SIZEOF_64B blocks*/
|
||||
|
@ -143,7 +145,7 @@ struct ByteMemory
|
|||
struct StaticMemoryDone
|
||||
{
|
||||
void (*init)(struct ByteMemory *byte_memory);
|
||||
void* (*malloc)(struct ByteMemory *byte_memory, x_size_t size);
|
||||
void* (*malloc)(struct ByteMemory *byte_memory, enum SmallSizeAllocSize size);
|
||||
void (*release)(void *pointer);
|
||||
};
|
||||
|
||||
|
@ -182,7 +184,7 @@ static int JudgeValidAddressRange(struct DynamicBuddyMemory *dynamic_buddy, void
|
|||
NULL_PARAM_CHECK(pointer);
|
||||
|
||||
/* the given address is between the physical start address and physical end address */
|
||||
if(((struct DynamicAllocNode *)pointer > dynamic_buddy->mm_dynamic_start[0]) && ((struct DynamicAllocNode *)pointer < dynamic_buddy->mm_dynamic_end[0])) {
|
||||
if (((struct DynamicAllocNode *)pointer > dynamic_buddy->mm_dynamic_start[0]) && ((struct DynamicAllocNode *)pointer < dynamic_buddy->mm_dynamic_end[0])) {
|
||||
return RET_TRUE;
|
||||
}
|
||||
/* invalid address */
|
||||
|
@ -349,11 +351,18 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz
|
|||
}
|
||||
|
||||
/* best-fit method */
|
||||
for (node = dynamic_buddy->mm_freenode_list[ndx].next;
|
||||
(ndx < MEM_LINKNRS ) && (node->size < allocsize);
|
||||
node = node->next) {
|
||||
ndx++;
|
||||
};
|
||||
node = dynamic_buddy->mm_freenode_list[ndx].next;
|
||||
while(ndx < MEM_LINKNRS && (NONE == node || node->size < allocsize)) {
|
||||
if (NONE == node) {
|
||||
ndx++;
|
||||
if (ndx == MEM_LINKNRS) { // no space to allocate
|
||||
return NONE;
|
||||
}
|
||||
node = dynamic_buddy->mm_freenode_list[ndx].next;
|
||||
} else {
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
/* get the best-fit freeNode */
|
||||
if (node && (node->size >= allocsize)) {
|
||||
struct DynamicFreeNode *remainder;
|
||||
|
@ -371,7 +380,7 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz
|
|||
|
||||
/* create the remainder node */
|
||||
remainder = PTR2FREENODE(((char *)node) + allocsize);
|
||||
remainder->size = remaining;
|
||||
remainder->size = remaining;
|
||||
|
||||
remainder->prev_adj_size = allocsize;
|
||||
remainder->flag = 0;
|
||||
|
@ -385,13 +394,12 @@ static void* BigMemMalloc(struct DynamicBuddyMemory *dynamic_buddy, x_size_t siz
|
|||
}
|
||||
|
||||
/* handle the case of an exact size match */
|
||||
|
||||
node->flag = extsram_mask;
|
||||
result = (void *)((char *)node + SIZEOF_DYNAMICALLOCNODE_MEM);
|
||||
}
|
||||
|
||||
/* failure allocation */
|
||||
if(result == NONE) {
|
||||
if (result == NONE) {
|
||||
#ifndef MEM_EXTERN_SRAM
|
||||
KPrintf("%s: allocation failed, size %d.\n", __func__, size);
|
||||
#endif
|
||||
|
@ -429,9 +437,9 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer)
|
|||
byte_memory->dynamic_buddy_manager.active_memory -= node->size;
|
||||
#endif
|
||||
/* get the next sibling freeNode */
|
||||
next = PTR2FREENODE((char*)node+node->size);
|
||||
next = PTR2FREENODE((char*)node + node->size);
|
||||
|
||||
if(((next->flag & DYNAMIC_BLOCK_MASK) == 0)) {
|
||||
if (((next->flag & DYNAMIC_BLOCK_MASK) == 0)) {
|
||||
struct DynamicAllocNode *andbeyond;
|
||||
|
||||
andbeyond = PTR2ALLOCNODE((char*)next + next->size);
|
||||
|
@ -446,7 +454,7 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer)
|
|||
}
|
||||
/* get the prev sibling freeNode */
|
||||
prev = (struct DynamicFreeNode*)((char*)node - node->prev_adj_size );
|
||||
if((prev->flag & DYNAMIC_BLOCK_MASK)==0) {
|
||||
if ((prev->flag & DYNAMIC_BLOCK_MASK) == 0) {
|
||||
|
||||
prev->prev->next=prev->next;
|
||||
if(prev->next){
|
||||
|
@ -459,7 +467,7 @@ static void BigMemFree( struct ByteMemory *byte_memory, void *pointer)
|
|||
node->flag = 0;
|
||||
|
||||
/* insert freeNode into dynamic buddy memory */
|
||||
AddNewNodeIntoBuddy(&byte_memory->dynamic_buddy_manager,node);
|
||||
AddNewNodeIntoBuddy(&byte_memory->dynamic_buddy_manager, node);
|
||||
}
|
||||
|
||||
static struct DynamicBuddyMemoryDone DynamicDone = {
|
||||
|
@ -545,12 +553,14 @@ static void SmallMemFree(void *pointer)
|
|||
NULL_PARAM_CHECK(pointer);
|
||||
|
||||
/* get the allocNode */
|
||||
node = PTR2ALLOCNODE((char*)pointer-SIZEOF_DYNAMICALLOCNODE_MEM);
|
||||
node = PTR2ALLOCNODE((char*)pointer - SIZEOF_DYNAMICALLOCNODE_MEM);
|
||||
static_segment = (struct segment*)(x_size_t)node->size;
|
||||
|
||||
/* update the statistic information of static_segment */
|
||||
node->size = (x_size_t)static_segment->freelist;
|
||||
static_segment->freelist = (uint8 *)node;
|
||||
node->flag = 0; // it's unnecessary, actually
|
||||
|
||||
static_segment->block_free_count++;
|
||||
|
||||
/* parameter detection */
|
||||
|
@ -565,7 +575,7 @@ static void SmallMemFree(void *pointer)
|
|||
*
|
||||
* @return pointer address on success; NULL on failure
|
||||
*/
|
||||
static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size)
|
||||
static void *SmallMemMalloc(struct ByteMemory *byte_memory, enum SmallSizeAllocSize size)
|
||||
{
|
||||
uint8 i = 0;
|
||||
void *result = NONE;
|
||||
|
@ -580,7 +590,7 @@ static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size)
|
|||
static_segment = &byte_memory->static_manager[1];
|
||||
|
||||
/* current static segment has free static memory block */
|
||||
if(static_segment->block_free_count>0) {
|
||||
if(static_segment->block_free_count > 0) {
|
||||
/* get the head static memory block */
|
||||
result = static_segment->freelist;
|
||||
node = PTR2ALLOCNODE(static_segment->freelist);
|
||||
|
@ -592,27 +602,14 @@ static void *SmallMemMalloc(struct ByteMemory *byte_memory, x_size_t size)
|
|||
node->size = (long)static_segment;
|
||||
}
|
||||
|
||||
if(result) {
|
||||
if (NONE != result) {
|
||||
/* return static memory block */
|
||||
return (char*)result + SIZEOF_DYNAMICALLOCNODE_MEM;
|
||||
}
|
||||
|
||||
/* the static memory block is exhausted, now turn to dynamic buddy memory for allocation. */
|
||||
result = byte_memory->dynamic_buddy_manager.done->malloc(&byte_memory->dynamic_buddy_manager, size, DYNAMIC_BLOCK_NO_EXTMEM_MASK);
|
||||
#ifdef MEM_EXTERN_SRAM
|
||||
if(NONE == result) {
|
||||
for(i = 0; i < EXTSRAM_MAX_NUM; i++) {
|
||||
if(NONE != ExtByteManager[i].done) {
|
||||
result = ExtByteManager[i].dynamic_buddy_manager.done->malloc(&ExtByteManager[i].dynamic_buddy_manager, size, DYNAMIC_BLOCK_EXTMEMn_MASK(i + 1));
|
||||
if (result){
|
||||
CHECK(ExtByteManager[i].dynamic_buddy_manager.done->JudgeLegal(&ExtByteManager[i].dynamic_buddy_manager, ret - SIZEOF_DYNAMICALLOCNODE_MEM));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
// fall to dynamic allocation
|
||||
return NONE;
|
||||
}
|
||||
|
||||
static struct StaticMemoryDone StaticDone = {
|
||||
|
@ -634,41 +631,46 @@ void *x_malloc(x_size_t size)
|
|||
void *ret = NONE;
|
||||
register x_base lock = 0;
|
||||
|
||||
/* parameter detection */
|
||||
/* hold lock before allocation */
|
||||
lock = CriticalAreaLock();
|
||||
|
||||
/* alignment */
|
||||
size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE);
|
||||
|
||||
/* parameter detection */
|
||||
#ifdef MEM_EXTERN_SRAM
|
||||
/* parameter detection */
|
||||
if(size == 0 ){
|
||||
return NONE;
|
||||
CriticalAreaUnLock(lock);
|
||||
return NONE;
|
||||
}
|
||||
if((size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory)){
|
||||
lock = CriticalAreaLock();
|
||||
/* alignment */
|
||||
size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE);
|
||||
goto try_extmem;
|
||||
}
|
||||
|
||||
#else
|
||||
/* parameter detection */
|
||||
if((size == 0) || (size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory))
|
||||
/* parameter detection */
|
||||
if((size == 0) || (size > ByteManager.dynamic_buddy_manager.dynamic_buddy_end - ByteManager.dynamic_buddy_manager.dynamic_buddy_start - ByteManager.dynamic_buddy_manager.active_memory)) {
|
||||
CriticalAreaUnLock(lock);
|
||||
return NONE;
|
||||
}
|
||||
#endif
|
||||
/* hold lock before allocation */
|
||||
lock = CriticalAreaLock();
|
||||
/* alignment */
|
||||
size = ALIGN_MEN_UP(size, MEM_ALIGN_SIZE);
|
||||
|
||||
/* determine allocation operation from static segments or dynamic buddy memory */
|
||||
#ifdef KERNEL_SMALL_MEM_ALLOC
|
||||
if(size <= SIZEOF_32B) {
|
||||
ret = ByteManager.static_manager[0].done->malloc(&ByteManager,SIZEOF_32B);
|
||||
} else if(size <= SIZEOF_64B) {
|
||||
ret = ByteManager.static_manager[1].done->malloc(&ByteManager,SIZEOF_64B);
|
||||
} else
|
||||
ret = ByteManager.static_manager[0].done->malloc(&ByteManager, SIZEOF_32B);
|
||||
} else if (size <= SIZEOF_64B) {
|
||||
ret = ByteManager.static_manager[1].done->malloc(&ByteManager, SIZEOF_64B);
|
||||
}
|
||||
#endif
|
||||
{
|
||||
|
||||
if (ret == NONE) {
|
||||
ret = ByteManager.dynamic_buddy_manager.done->malloc(&ByteManager.dynamic_buddy_manager, size, DYNAMIC_BLOCK_NO_EXTMEM_MASK);
|
||||
if(ret != NONE)
|
||||
if (ret != NONE) {
|
||||
CHECK(ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager, ret - SIZEOF_DYNAMICALLOCNODE_MEM));
|
||||
}
|
||||
|
||||
#ifdef MEM_EXTERN_SRAM
|
||||
try_extmem:
|
||||
|
@ -686,6 +688,7 @@ try_extmem:
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* release lock */
|
||||
CriticalAreaUnLock(lock);
|
||||
return ret;
|
||||
|
@ -781,14 +784,20 @@ void x_free(void *pointer)
|
|||
struct DynamicAllocNode *node = NONE;
|
||||
|
||||
/* parameter detection */
|
||||
if (pointer == NONE)
|
||||
return ;
|
||||
|
||||
CHECK(ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager,pointer));
|
||||
if (pointer == NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* hold lock before release */
|
||||
lock = CriticalAreaLock();
|
||||
node = PTR2ALLOCNODE((char*)pointer-SIZEOF_DYNAMICALLOCNODE_MEM);
|
||||
|
||||
if (!ByteManager.dynamic_buddy_manager.done->JudgeLegal(&ByteManager.dynamic_buddy_manager, pointer)) {
|
||||
CriticalAreaUnLock(lock);
|
||||
SYS_ERR("[%s] Freeing a unallocated address.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
node = PTR2ALLOCNODE((char*)pointer - SIZEOF_DYNAMICALLOCNODE_MEM);
|
||||
CHECK(ByteManager.done->JudgeAllocated(node));
|
||||
|
||||
/* judge release the memory block ro static_segment or dynamic buddy memory */
|
||||
|
@ -799,19 +808,20 @@ void x_free(void *pointer)
|
|||
#endif
|
||||
{
|
||||
#ifdef MEM_EXTERN_SRAM
|
||||
/* judge the pointer is not malloced from extern memory*/
|
||||
if(0 == (node->flag & 0xFF0000)) {
|
||||
ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer);
|
||||
}
|
||||
/* judge the pointer is not malloced from extern memory*/
|
||||
if(0 == (node->flag & 0xFF0000)) {
|
||||
ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer);
|
||||
}
|
||||
|
||||
/* judge the pointer is malloced from extern memory*/
|
||||
if(0 != (node->flag & 0xFF0000)) {
|
||||
ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1].dynamic_buddy_manager.done->release(&ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1],pointer);
|
||||
}
|
||||
/* judge the pointer is malloced from extern memory*/
|
||||
if(0 != (node->flag & 0xFF0000)) {
|
||||
ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1].dynamic_buddy_manager.done->release(&ExtByteManager[((node->flag & 0xFF0000) >> 16) - 1],pointer);
|
||||
}
|
||||
#else
|
||||
ByteManager.dynamic_buddy_manager.done->release(&ByteManager,pointer);
|
||||
ByteManager.dynamic_buddy_manager.done->release(&ByteManager, pointer);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* release the lock */
|
||||
CriticalAreaUnLock(lock);
|
||||
}
|
||||
|
@ -888,7 +898,8 @@ void InitBoardMemory(void *start_phy_address, void *end_phy_address)
|
|||
/* parameter detection */
|
||||
if (ByteManager.dynamic_buddy_manager.dynamic_buddy_start >= ByteManager.dynamic_buddy_manager.dynamic_buddy_end) {
|
||||
//KPrintf("InitBoardMemory, wrong address[0x%x - 0x%x]\n", (x_ubase)start_phy_address, (x_ubase)end_phy_address);
|
||||
return;
|
||||
SYS_KDEBUG_LOG(KDBG_MEM, ("InitBoardMemory, wrong address[0x%x - 0x%x]\n", (x_ubase)start_phy_address, (x_ubase)end_phy_address));
|
||||
return;
|
||||
}
|
||||
|
||||
mheap->mm_total_size = 0;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
DoubleLinklistType xiaoshan_delay_head = {&xiaoshan_delay_head, &xiaoshan_delay_head};
|
||||
|
||||
/**
|
||||
* This function will delay a task with sone ticks.
|
||||
* This function will delay a task with some ticks.
|
||||
*
|
||||
* @param task the task needed to be delayed
|
||||
* @param ticks delay timeout
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <xizi.h>
|
||||
#include <xs_delay.h>
|
||||
#include <xs_kdbg.h>
|
||||
|
||||
DECLARE_ID_MANAGER(k_mq_id_manager, ID_NUM_MAX);
|
||||
DoubleLinklistType k_mq_list = {&k_mq_list, &k_mq_list};
|
||||
|
@ -41,17 +42,17 @@ static struct MsgQueue *GetMsgQueueById(int32 id)
|
|||
|
||||
lock = CriticalAreaLock();
|
||||
idnode = IdGetObj(&k_mq_id_manager, id);
|
||||
if (idnode == NONE){
|
||||
CriticalAreaUnLock(lock);
|
||||
return NONE;
|
||||
if (idnode == NONE) {
|
||||
CriticalAreaUnLock(lock);
|
||||
return NONE;
|
||||
}
|
||||
mq = CONTAINER_OF(idnode, struct MsgQueue, id);
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
return mq;
|
||||
}
|
||||
|
||||
static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size,
|
||||
x_size_t max_msgs )
|
||||
static x_err_t _InitMsgQueue(struct MsgQueue* mq, x_size_t msg_size, x_size_t max_msgs)
|
||||
{
|
||||
x_base lock = 0;
|
||||
|
||||
|
@ -62,10 +63,12 @@ static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size,
|
|||
mq->each_len = ALIGN_MEN_UP(msg_size, MEM_ALIGN_SIZE);
|
||||
mq->index = 0;
|
||||
|
||||
SYS_KDEBUG_LOG(MSGQUEUE_DEBUG, ("[%s] Msg attr, max_msg_num: %d, block size: %d\n", __func__, mq->max_msgs, mq->each_len));
|
||||
|
||||
InitDoubleLinkList(&mq->send_pend_list);
|
||||
InitDoubleLinkList(&(mq->recv_pend_list));
|
||||
|
||||
mq->msg_buf = x_malloc( mq->each_len * mq->max_msgs);
|
||||
mq->msg_buf = x_malloc(mq->each_len * mq->max_msgs);
|
||||
if (mq->msg_buf == NONE) {
|
||||
lock = CriticalAreaLock();
|
||||
DoubleLinkListRmNode(&(mq->link));
|
||||
|
@ -77,26 +80,28 @@ static x_err_t _InitMsgQueue( struct MsgQueue *mq ,x_size_t msg_size,
|
|||
return EOK;
|
||||
}
|
||||
|
||||
static x_err_t _MsgQueueSend(struct MsgQueue *mq,
|
||||
const void *buffer,
|
||||
x_size_t size,
|
||||
int32 msec)
|
||||
static x_err_t _MsgQueueSend(struct MsgQueue* mq,
|
||||
const void* buffer,
|
||||
x_size_t size,
|
||||
int32 msec)
|
||||
{
|
||||
x_ubase lock = 0;
|
||||
uint32 tick_delta = 0;
|
||||
int32 timeout = 0;
|
||||
uint8 *msg = NONE;
|
||||
uint8* msg = NONE;
|
||||
struct TaskDescriptor *task = NONE;
|
||||
|
||||
NULL_PARAM_CHECK(mq);
|
||||
NULL_PARAM_CHECK(buffer);
|
||||
|
||||
SYS_KDEBUG_LOG(MSGQUEUE_DEBUG, ("[%s] mq_num_msgs: %d, block size: %d, needed size: %d\n", __func__, mq->num_msgs, mq->each_len, size));
|
||||
|
||||
if (size > mq->each_len)
|
||||
return -ERROR;
|
||||
|
||||
tick_delta = 0;
|
||||
task = GetKTaskDescriptor();
|
||||
if(WAITING_FOREVER == msec)
|
||||
if (WAITING_FOREVER == msec)
|
||||
timeout = WAITING_FOREVER;
|
||||
else
|
||||
timeout = CalculateTickFromTimeMs(msec);
|
||||
|
@ -107,8 +112,7 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq,
|
|||
return -EFULL;
|
||||
}
|
||||
|
||||
while(mq->num_msgs >= mq->max_msgs ) {
|
||||
|
||||
while (mq->num_msgs >= mq->max_msgs) {
|
||||
task->exstatus = EOK;
|
||||
if (timeout == 0) {
|
||||
CriticalAreaUnLock(lock);
|
||||
|
@ -121,7 +125,7 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq,
|
|||
tick_delta = CurrentTicksGain();
|
||||
SYS_KDEBUG_LOG(KDBG_IPC, ("mq_send_wait: start timer of task:%s\n",
|
||||
task->task_base_info.name));
|
||||
KTaskSetDelay(task,timeout);
|
||||
KTaskSetDelay(task, timeout);
|
||||
}
|
||||
|
||||
CriticalAreaUnLock(lock);
|
||||
|
@ -139,19 +143,19 @@ static x_err_t _MsgQueueSend(struct MsgQueue *mq,
|
|||
if (timeout < 0)
|
||||
timeout = 0;
|
||||
}
|
||||
}
|
||||
} // end with lock here
|
||||
|
||||
msg = mq->msg_buf + ( ( mq->index + mq->num_msgs ) % mq->max_msgs ) * mq->each_len ;
|
||||
msg = mq->msg_buf + ((mq->index + mq->num_msgs) % mq->max_msgs) * mq->each_len;
|
||||
memcpy(msg, buffer, size);
|
||||
mq->num_msgs ++;
|
||||
mq->num_msgs++;
|
||||
if (!IsDoubleLinkListEmpty(&mq->recv_pend_list)) {
|
||||
LinklistResume(&(mq->recv_pend_list));
|
||||
CriticalAreaUnLock(lock);
|
||||
DO_KTASK_ASSIGN;
|
||||
return EOK;
|
||||
}
|
||||
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
|
@ -191,15 +195,15 @@ static x_err_t _MsgQueueUrgentSend(struct MsgQueue *mq, const void *buffer, x_si
|
|||
return EOK;
|
||||
}
|
||||
|
||||
static x_err_t _MsgQueueRecv(struct MsgQueue *mq,
|
||||
void *buffer,
|
||||
x_size_t size,
|
||||
int32 msec)
|
||||
static x_err_t _MsgQueueRecv(struct MsgQueue* mq,
|
||||
void* buffer,
|
||||
x_size_t size,
|
||||
int32 msec)
|
||||
{
|
||||
x_ubase lock = 0;
|
||||
uint32 tick_delta = 0;
|
||||
int32 timeout = 0;
|
||||
struct MqMessage *msg = NONE;
|
||||
uint8* msg = NONE;
|
||||
struct TaskDescriptor *task = NONE;
|
||||
|
||||
NULL_PARAM_CHECK(mq);
|
||||
|
@ -208,14 +212,14 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq,
|
|||
tick_delta = 0;
|
||||
task = GetKTaskDescriptor();
|
||||
timeout = CalculateTickFromTimeMs(msec);
|
||||
lock = CriticalAreaLock();
|
||||
|
||||
lock = CriticalAreaLock();
|
||||
if (mq->index == 0 && timeout == 0) {
|
||||
CriticalAreaUnLock(lock);
|
||||
return -ETIMEOUT;
|
||||
}
|
||||
|
||||
for( ; mq->num_msgs <= 0 ; ) {
|
||||
while (mq->num_msgs <= 0) {
|
||||
KDEBUG_IN_KTASK_CONTEXT;
|
||||
|
||||
task->exstatus = EOK;
|
||||
|
@ -225,19 +229,16 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq,
|
|||
return -ETIMEOUT;
|
||||
}
|
||||
|
||||
LinklistSuspend(&(mq->recv_pend_list),
|
||||
task,
|
||||
LINKLIST_FLAG_FIFO);
|
||||
LinklistSuspend(&(mq->recv_pend_list), task, LINKLIST_FLAG_FIFO);
|
||||
|
||||
if (timeout > 0) {
|
||||
tick_delta = CurrentTicksGain();
|
||||
SYS_KDEBUG_LOG(KDBG_IPC, ("set task:%s to timer list\n",
|
||||
task->task_base_info.name));
|
||||
KTaskSetDelay(task,timeout);
|
||||
KTaskSetDelay(task, timeout);
|
||||
}
|
||||
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
DO_KTASK_ASSIGN;
|
||||
|
||||
if (task->exstatus != EOK) {
|
||||
|
@ -256,8 +257,8 @@ static x_err_t _MsgQueueRecv(struct MsgQueue *mq,
|
|||
|
||||
msg = mq->msg_buf + mq->index * mq->each_len;
|
||||
mq->index = (mq->index + 1) % mq->max_msgs;
|
||||
memcpy(buffer, msg , size > mq->each_len ? mq->each_len : size);
|
||||
mq->num_msgs --;
|
||||
memcpy(buffer, msg, size > mq->each_len ? mq->each_len : size);
|
||||
mq->num_msgs--;
|
||||
|
||||
if (!IsDoubleLinkListEmpty(&(mq->send_pend_list))) {
|
||||
LinklistResume(&(mq->send_pend_list));
|
||||
|
@ -326,8 +327,7 @@ static struct MsgQueueDone Done = {
|
|||
*
|
||||
* @return id on success;ENOMEMORY/ERROR on failure
|
||||
*/
|
||||
int32 KCreateMsgQueue(x_size_t msg_size,
|
||||
x_size_t max_msgs)
|
||||
int32 KCreateMsgQueue(x_size_t msg_size, x_size_t max_msgs)
|
||||
{
|
||||
int32 id = 0;
|
||||
x_base temp = 0;
|
||||
|
@ -337,11 +337,12 @@ int32 KCreateMsgQueue(x_size_t msg_size,
|
|||
mq = (struct MsgQueue *)x_malloc(sizeof(struct MsgQueue));
|
||||
if (mq == NONE)
|
||||
return -ENOMEMORY;
|
||||
memset(mq,0x0,sizeof(struct MsgQueue));
|
||||
memset(mq, 0x0, sizeof(struct MsgQueue));
|
||||
|
||||
lock = CriticalAreaLock();
|
||||
id = IdInsertObj(&k_mq_id_manager, &mq->id);
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
if (id < 0) {
|
||||
x_free(mq);
|
||||
return -ENOMEMORY;
|
||||
|
@ -350,11 +351,12 @@ int32 KCreateMsgQueue(x_size_t msg_size,
|
|||
lock = CriticalAreaLock();
|
||||
DoubleLinkListInsertNodeAfter(&k_mq_list, &mq->link);
|
||||
CriticalAreaUnLock(lock);
|
||||
|
||||
mq->Done = &Done;
|
||||
if( mq->Done->init(mq, msg_size,max_msgs) == EOK )
|
||||
return mq->id.id;
|
||||
if (mq->Done->init(mq, msg_size, max_msgs) == EOK)
|
||||
return mq->id.id;
|
||||
else
|
||||
return -ERROR;
|
||||
return -ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -401,7 +403,7 @@ x_err_t KMsgQueueRecv(int32 id,
|
|||
|
||||
mq = GetMsgQueueById(id);
|
||||
if (mq != NONE)
|
||||
return mq->Done->recv(mq,buffer,size,timeout);
|
||||
return mq->Done->recv(mq, buffer, size, timeout);
|
||||
else
|
||||
return -EINVALED;
|
||||
|
||||
|
@ -471,10 +473,11 @@ x_err_t KMsgQueueSend(int32 id, const void *buffer, x_size_t size)
|
|||
|
||||
mq = GetMsgQueueById(id);
|
||||
if (mq != NONE)
|
||||
return mq->Done->send(mq,buffer,size,0);
|
||||
return mq->Done->send(mq, buffer, size, WAITING_FOREVER);
|
||||
else
|
||||
return -EINVALED;
|
||||
}
|
||||
|
||||
/**
|
||||
* send message with waiting time,current suspend task will be resumed
|
||||
*
|
||||
|
|
|
@ -8,6 +8,9 @@ ifeq ($(CONFIG_APP_SELECT_NEWLIB), y)
|
|||
APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/lib/app_newlib/include #
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APP_USING_WEBNET),y)
|
||||
APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/inc #
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ADD_XIZI_FEATURES), y)
|
||||
APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/transform_layer/xizi \
|
||||
|
@ -36,6 +39,7 @@ ifeq ($(CONFIG_CRYPTO), y)
|
|||
APPPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Framework/security/crypto/include #
|
||||
endif
|
||||
|
||||
|
||||
# COMPILE_APP:
|
||||
# @$(eval CPPPATHS=$(APPPATHS))
|
||||
# @echo $(SRC_APP_DIR)
|
||||
|
|
|
@ -52,6 +52,8 @@ KERNELPATHS += \
|
|||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -86,6 +88,8 @@ KERNELPATHS += \
|
|||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -334,6 +338,8 @@ KERNELPATHS += \
|
|||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -365,6 +371,8 @@ KERNELPATHS += \
|
|||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -419,6 +427,8 @@ KERNELPATHS += \
|
|||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/priv \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/include/lwip/prot \
|
||||
-I$(KERNEL_ROOT)/resources/ethernet/LwIP/arch
|
||||
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/resources/include/netdev
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -554,9 +564,16 @@ endif
|
|||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_APP_USING_WEBNET),y)
|
||||
KERNELPATHS += -I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/inc \
|
||||
-I$(KERNEL_ROOT)/../../APP_Framework/Applications/webnet/WebNet_XiUOS/samples #
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(CONFIG_TOOL_SHELL), y)
|
||||
KERNELPATHS +=-I$(KERNEL_ROOT)/tool/shell/letter-shell \
|
||||
-I$(KERNEL_ROOT)/tool/shell/letter-shell/file_ext #
|
||||
-I$(KERNEL_ROOT)/tool/shell/letter-shell/file_ext \
|
||||
-I$(KERNEL_ROOT)/tool/shell/
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TOOL_USING_OTA), y)
|
||||
|
|
|
@ -540,7 +540,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums
|
|||
#define TCPIP_THREAD_NAME "tcp"
|
||||
#define TCPIP_THREAD_STACKSIZE 2048
|
||||
#define TCPIP_MBOX_SIZE 16
|
||||
#define TCPIP_THREAD_PRIO 20
|
||||
#define TCPIP_THREAD_PRIO 30
|
||||
|
||||
/*
|
||||
----------------------------------------
|
||||
|
|
|
@ -31,55 +31,54 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @file sys_arch.c
|
||||
* @brief In order to adapt to XiZi, some changes have been made to implement the LwIP interface.
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
* @file sys_arch.c
|
||||
* @brief In order to adapt to XiZi, some changes have been made to implement the LwIP interface.
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-05-29
|
||||
*/
|
||||
#include "debug.h"
|
||||
|
||||
#include <lwip/opt.h>
|
||||
#include <lwip/arch.h>
|
||||
#include <lwip/opt.h>
|
||||
|
||||
#include "tcpip.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/sio.h"
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/debug.h>
|
||||
#include <lwip/sys.h>
|
||||
#include "lwip/dhcp.h"
|
||||
#include "tcpip.h"
|
||||
#include "tcpip_priv.h"
|
||||
#include <lwip/debug.h>
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/sys.h>
|
||||
|
||||
#if !NO_SYS
|
||||
#include "sys_arch.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <xs_assign.h>
|
||||
#include <xs_ktask.h>
|
||||
#include <xs_ktick.h>
|
||||
#include <xs_assign.h>
|
||||
#include <xs_sem.h>
|
||||
#include <xs_mutex.h>
|
||||
#include <xs_ktask.h>
|
||||
#include <xs_msg.h>
|
||||
#include <xs_mutex.h>
|
||||
#include <xs_sem.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "ethernet.h"
|
||||
#include "connect_ethernet.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
char lwip_ipaddr[20] = {192, 168, 130, 77};
|
||||
char lwip_netmask[20] = {255, 255, 254, 0};
|
||||
char lwip_gwaddr[20] = {192, 168, 130, 1};
|
||||
char lwip_ipaddr[20] = { 192, 168, 130, 77 };
|
||||
char lwip_netmask[20] = { 255, 255, 254, 0 };
|
||||
char lwip_gwaddr[20] = { 192, 168, 130, 1 };
|
||||
|
||||
char lwip_eth0_ipaddr[20] = {192, 168, 130, 77};
|
||||
char lwip_eth0_netmask[20] = {255, 255, 254, 0};
|
||||
char lwip_eth0_gwaddr[20] = {192, 168, 130, 1};
|
||||
char lwip_eth0_ipaddr[20] = { 192, 168, 130, 77 };
|
||||
char lwip_eth0_netmask[20] = { 255, 255, 254, 0 };
|
||||
char lwip_eth0_gwaddr[20] = { 192, 168, 130, 1 };
|
||||
|
||||
char lwip_eth1_ipaddr[20] = {192, 168, 130, 99};
|
||||
char lwip_eth1_netmask[20] = {255, 255, 254, 0};
|
||||
char lwip_eth1_gwaddr[20] = {192, 168, 130, 23};
|
||||
char lwip_eth1_ipaddr[20] = { 192, 168, 130, 99 };
|
||||
char lwip_eth1_netmask[20] = { 255, 255, 254, 0 };
|
||||
char lwip_eth1_gwaddr[20] = { 192, 168, 130, 23 };
|
||||
|
||||
char lwip_flag = 0;
|
||||
|
||||
|
@ -88,220 +87,238 @@ x_ticks_t lwip_sys_now;
|
|||
#define SYS_THREAD_MAX 4
|
||||
|
||||
struct netif gnetif;
|
||||
sys_sem_t* get_eth_recv_sem() {
|
||||
sys_sem_t* get_eth_recv_sem()
|
||||
{
|
||||
static sys_sem_t g_recv_sem = 0;
|
||||
return &g_recv_sem;
|
||||
}
|
||||
|
||||
void sys_init(void) {
|
||||
// do nothing
|
||||
void sys_init(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
u32_t
|
||||
sys_jiffies(void) {
|
||||
lwip_sys_now = CurrentTicksGain();
|
||||
return lwip_sys_now;
|
||||
u32_t sys_jiffies(void)
|
||||
{
|
||||
lwip_sys_now = CurrentTicksGain();
|
||||
return lwip_sys_now;
|
||||
}
|
||||
|
||||
u32_t
|
||||
sys_now(void) {
|
||||
lwip_sys_now = CurrentTicksGain();
|
||||
return CalculateTimeMsFromTick(lwip_sys_now);
|
||||
u32_t sys_now(void)
|
||||
{
|
||||
lwip_sys_now = CurrentTicksGain();
|
||||
return CalculateTimeMsFromTick(lwip_sys_now);
|
||||
}
|
||||
|
||||
sys_prot_t sys_arch_protect(void) {
|
||||
return CriticalAreaLock();
|
||||
sys_prot_t sys_arch_protect(void)
|
||||
{
|
||||
return CriticalAreaLock();
|
||||
}
|
||||
|
||||
void sys_arch_unprotect(sys_prot_t pval) {
|
||||
CriticalAreaUnLock(pval);
|
||||
void sys_arch_unprotect(sys_prot_t pval)
|
||||
{
|
||||
CriticalAreaUnLock(pval);
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
|
||||
err_t
|
||||
sys_sem_new(sys_sem_t *sem, u8_t count) {
|
||||
*sem = KSemaphoreCreate((uint16)count);
|
||||
err_t sys_sem_new(sys_sem_t* sem, u8_t count)
|
||||
{
|
||||
*sem = KSemaphoreCreate((uint16)count);
|
||||
|
||||
#if SYS_STATS
|
||||
++lwip_stats.sys.sem.used;
|
||||
if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
|
||||
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
|
||||
}
|
||||
#endif /* SYS_STATS */
|
||||
|
||||
if(*sem >= 0)
|
||||
return ERR_OK;
|
||||
else {
|
||||
#if SYS_STATS
|
||||
++lwip_stats.sys.sem.err;
|
||||
#endif /* SYS_STATS */
|
||||
KPrintf("[sys_arch]:new sem fail!\n");
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_free(sys_sem_t *sem) {
|
||||
#if SYS_STATS
|
||||
--lwip_stats.sys.sem.used;
|
||||
#endif /* SYS_STATS */
|
||||
KSemaphoreDelete(*sem);
|
||||
*sem = SYS_SEM_NULL;
|
||||
}
|
||||
|
||||
int sys_sem_valid(sys_sem_t *sem) {
|
||||
return (*sem > SYS_SEM_NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_set_invalid(sys_sem_t *sem) {
|
||||
*sem = SYS_SEM_NULL;
|
||||
}
|
||||
|
||||
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) {
|
||||
x_ticks_t start_tick = 0 ;
|
||||
int32 wait_time = 0;
|
||||
|
||||
|
||||
if(*sem == SYS_SEM_NULL)
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
|
||||
|
||||
start_tick = CurrentTicksGain();
|
||||
|
||||
if (0 == timeout)
|
||||
wait_time = WAITING_FOREVER;
|
||||
else
|
||||
wait_time = timeout;
|
||||
|
||||
|
||||
if(KSemaphoreObtain(*sem, wait_time) == EOK)
|
||||
return CalculateTimeMsFromTick(CurrentTicksGain()-start_tick);
|
||||
else
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
void sys_sem_signal(sys_sem_t *sem) {
|
||||
if(KSemaphoreAbandon(*sem) != EOK)
|
||||
KPrintf("[sys_arch]:sem signal fail!\n");
|
||||
}
|
||||
|
||||
err_t sys_mutex_new(sys_mutex_t *mutex) {
|
||||
*mutex = KMutexCreate();
|
||||
if (*mutex > SYS_MRTEX_NULL)
|
||||
return ERR_OK;
|
||||
else {
|
||||
KPrintf("[sys_arch]:new mutex fail!\n");
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_mutex_free(sys_mutex_t *mutex) {
|
||||
KMutexDelete(*mutex);
|
||||
}
|
||||
|
||||
void sys_mutex_set_invalid(sys_mutex_t *mutex) {
|
||||
*mutex = SYS_MRTEX_NULL;
|
||||
}
|
||||
|
||||
void sys_mutex_lock(sys_mutex_t *mutex) {
|
||||
KMutexObtain(*mutex, WAITING_FOREVER);
|
||||
}
|
||||
|
||||
void sys_mutex_unlock(sys_mutex_t *mutex) {
|
||||
KMutexAbandon(*mutex);
|
||||
}
|
||||
|
||||
|
||||
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio) {
|
||||
sys_thread_t handle = -1;
|
||||
handle = KTaskCreate(name,
|
||||
function,
|
||||
arg,
|
||||
(uint32)stacksize,
|
||||
(uint8)prio);
|
||||
if (handle >= 0) {
|
||||
StartupKTask(handle);
|
||||
lw_print("lw: [%s] create %s handle %x\n", __func__, name, handle);
|
||||
return handle;
|
||||
}
|
||||
lw_print("lw: [%s] create %s failed\n", __func__, name);
|
||||
return -ERROR;
|
||||
}
|
||||
|
||||
err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
|
||||
*mbox = KCreateMsgQueue(sizeof(void *), size);
|
||||
|
||||
#if SYS_STATS
|
||||
++lwip_stats.sys.mbox.used;
|
||||
if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
|
||||
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
|
||||
++lwip_stats.sys.sem.used;
|
||||
if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
|
||||
lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
|
||||
}
|
||||
#endif /* SYS_STATS */
|
||||
if(*mbox < 0) {
|
||||
lw_print("lw: [%s] alloc %d mbox %p failed\n", __func__, size, mbox);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
lw_print("lw: [%s] alloc %d mbox %p ok!\n", __func__, size, mbox);
|
||||
return ERR_OK;
|
||||
if (*sem >= 0)
|
||||
return ERR_OK;
|
||||
else {
|
||||
#if SYS_STATS
|
||||
++lwip_stats.sys.sem.err;
|
||||
#endif /* SYS_STATS */
|
||||
KPrintf("[sys_arch]:new sem fail!\n");
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_mbox_free(sys_mbox_t *mbox) {
|
||||
KDeleteMsgQueue(*mbox);
|
||||
void sys_sem_free(sys_sem_t* sem)
|
||||
{
|
||||
#if SYS_STATS
|
||||
--lwip_stats.sys.sem.used;
|
||||
#endif /* SYS_STATS */
|
||||
KSemaphoreDelete(*sem);
|
||||
*sem = SYS_SEM_NULL;
|
||||
}
|
||||
|
||||
int sys_mbox_valid(sys_mbox_t *mbox) {
|
||||
if (*mbox <= SYS_MBOX_NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
int sys_sem_valid(sys_sem_t* sem)
|
||||
{
|
||||
return (*sem > SYS_SEM_NULL);
|
||||
}
|
||||
|
||||
void sys_mbox_set_invalid(sys_mbox_t *mbox) {
|
||||
*mbox = SYS_MBOX_NULL;
|
||||
void sys_sem_set_invalid(sys_sem_t* sem)
|
||||
{
|
||||
*sem = SYS_SEM_NULL;
|
||||
}
|
||||
|
||||
void sys_mbox_post(sys_mbox_t *q, void *msg) {
|
||||
KMsgQueueSendwait(*q, &msg, sizeof(void *), WAITING_FOREVER);
|
||||
u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
|
||||
{
|
||||
x_ticks_t start_tick = 0;
|
||||
int32 wait_time = 0;
|
||||
|
||||
if (*sem == SYS_SEM_NULL)
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
|
||||
start_tick = CurrentTicksGain();
|
||||
|
||||
if (0 == timeout)
|
||||
wait_time = WAITING_FOREVER;
|
||||
else
|
||||
wait_time = timeout;
|
||||
|
||||
if (KSemaphoreObtain(*sem, wait_time) == EOK)
|
||||
return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick);
|
||||
else
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost(sys_mbox_t *q, void *msg) {
|
||||
// if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK)
|
||||
if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK)
|
||||
void sys_sem_signal(sys_sem_t* sem)
|
||||
{
|
||||
if (KSemaphoreAbandon(*sem) != EOK)
|
||||
KPrintf("[sys_arch]:sem signal fail!\n");
|
||||
}
|
||||
|
||||
err_t sys_mutex_new(sys_mutex_t* mutex)
|
||||
{
|
||||
*mutex = KMutexCreate();
|
||||
if (*mutex > SYS_MRTEX_NULL)
|
||||
return ERR_OK;
|
||||
else {
|
||||
KPrintf("[sys_arch]:new mutex fail!\n");
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_mutex_free(sys_mutex_t* mutex)
|
||||
{
|
||||
KMutexDelete(*mutex);
|
||||
}
|
||||
|
||||
void sys_mutex_set_invalid(sys_mutex_t* mutex)
|
||||
{
|
||||
*mutex = SYS_MRTEX_NULL;
|
||||
}
|
||||
|
||||
void sys_mutex_lock(sys_mutex_t* mutex)
|
||||
{
|
||||
KMutexObtain(*mutex, WAITING_FOREVER);
|
||||
}
|
||||
|
||||
void sys_mutex_unlock(sys_mutex_t* mutex)
|
||||
{
|
||||
KMutexAbandon(*mutex);
|
||||
}
|
||||
|
||||
sys_thread_t sys_thread_new(const char* name, lwip_thread_fn function, void* arg, int stacksize, int prio)
|
||||
{
|
||||
sys_thread_t handle = -1;
|
||||
handle = KTaskCreate(name,
|
||||
function,
|
||||
arg,
|
||||
(uint32)stacksize,
|
||||
(uint8)prio);
|
||||
if (handle >= 0) {
|
||||
StartupKTask(handle);
|
||||
lw_print("lw: [%s] create %s handle %x\n", __func__, name, handle);
|
||||
return handle;
|
||||
}
|
||||
lw_print("lw: [%s] create %s failed\n", __func__, name);
|
||||
return -ERROR;
|
||||
}
|
||||
|
||||
err_t sys_mbox_new(sys_mbox_t* mbox, int size)
|
||||
{
|
||||
*mbox = KCreateMsgQueue(sizeof(void*), size);
|
||||
|
||||
#if SYS_STATS
|
||||
++lwip_stats.sys.mbox.used;
|
||||
if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
|
||||
lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
|
||||
}
|
||||
#endif /* SYS_STATS */
|
||||
if (*mbox < 0) {
|
||||
lw_print("lw: [%s] alloc %d mbox %p failed\n", __func__, size, mbox);
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
lw_print("lw: [%s] alloc %d mbox %p ok!\n", __func__, size, mbox);
|
||||
return ERR_OK;
|
||||
else
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg) {
|
||||
return sys_mbox_trypost(q, msg);
|
||||
void sys_mbox_free(sys_mbox_t* mbox)
|
||||
{
|
||||
KDeleteMsgQueue(*mbox);
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout) {
|
||||
x_ticks_t start_tick = 0 ;
|
||||
int32 wait_time = 0;
|
||||
|
||||
start_tick = CurrentTicksGain();
|
||||
|
||||
if (0 == timeout)
|
||||
wait_time = WAITING_FOREVER;
|
||||
else
|
||||
wait_time = timeout;
|
||||
|
||||
if(KMsgQueueRecv(*q, &(*msg), sizeof(void *), wait_time) == EOK) {
|
||||
return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick);
|
||||
} else {
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
int sys_mbox_valid(sys_mbox_t* mbox)
|
||||
{
|
||||
if (*mbox <= SYS_MBOX_NULL)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg) {
|
||||
if (KMsgQueueRecv(*q, &(*msg), sizeof(void *), 0) == EOK)
|
||||
return ERR_OK;
|
||||
else
|
||||
return SYS_MBOX_EMPTY;
|
||||
void sys_mbox_set_invalid(sys_mbox_t* mbox)
|
||||
{
|
||||
*mbox = SYS_MBOX_NULL;
|
||||
}
|
||||
|
||||
void sys_mbox_post(sys_mbox_t* q, void* msg)
|
||||
{
|
||||
KMsgQueueSendwait(*q, &msg, sizeof(void*), WAITING_FOREVER);
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost(sys_mbox_t* q, void* msg)
|
||||
{
|
||||
// if(KMsgQueueSend(*q, &msg, sizeof(void *)) == EOK)
|
||||
if (KMsgQueueSend(*q, &msg, sizeof(void*)) == EOK)
|
||||
return ERR_OK;
|
||||
else
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost_fromisr(sys_mbox_t* q, void* msg)
|
||||
{
|
||||
return sys_mbox_trypost(q, msg);
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t* q, void** msg, u32_t timeout)
|
||||
{
|
||||
x_ticks_t start_tick = 0;
|
||||
int32 wait_time = 0;
|
||||
|
||||
start_tick = CurrentTicksGain();
|
||||
|
||||
if (0 == timeout)
|
||||
wait_time = WAITING_FOREVER;
|
||||
else
|
||||
wait_time = timeout;
|
||||
|
||||
if (KMsgQueueRecv(*q, &(*msg), sizeof(void*), wait_time) == EOK) {
|
||||
return CalculateTimeMsFromTick(CurrentTicksGain() - start_tick);
|
||||
} else {
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t* q, void** msg)
|
||||
{
|
||||
if (KMsgQueueRecv(*q, &(*msg), sizeof(void*), 0) == EOK)
|
||||
return ERR_OK;
|
||||
else
|
||||
return SYS_MBOX_EMPTY;
|
||||
}
|
||||
|
||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
||||
|
@ -315,128 +332,136 @@ ip4_addr_t ipaddr;
|
|||
ip4_addr_t netmask;
|
||||
ip4_addr_t gw;
|
||||
|
||||
void lwip_config_input(struct netif *net) {
|
||||
sys_thread_t th_id = 0;
|
||||
void lwip_config_input(struct netif* net)
|
||||
{
|
||||
sys_thread_t th_id = 0;
|
||||
|
||||
th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 20);
|
||||
th_id = sys_thread_new("eth_input", ethernetif_input, net, LWIP_TASK_STACK_SIZE, 30);
|
||||
|
||||
if (th_id >= 0) {
|
||||
lw_print("%s %d successfully!\n", __func__, th_id);
|
||||
} else {
|
||||
lw_print("%s failed!\n", __func__);
|
||||
}
|
||||
if (th_id >= 0) {
|
||||
lw_print("%s %d successfully!\n", __func__, th_id);
|
||||
} else {
|
||||
lw_print("%s failed!\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void lwip_config_tcp(uint8_t enet_port, char *ip, char *mask, char *gw) {
|
||||
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
||||
char* eth_cfg;
|
||||
void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw)
|
||||
{
|
||||
static char is_init = 0;
|
||||
if (is_init != 0) {
|
||||
return;
|
||||
}
|
||||
is_init = 1;
|
||||
|
||||
eth_cfg = ethernetif_config_enet_set(enet_port);
|
||||
sys_sem_new(get_eth_recv_sem(), 0);
|
||||
|
||||
if(chk_lwip_bit(LWIP_INIT_FLAG)) {
|
||||
lw_print("lw: [%s] already ...\n", __func__);
|
||||
return;
|
||||
}
|
||||
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
||||
char* eth_cfg;
|
||||
|
||||
set_lwip_bit(LWIP_INIT_FLAG);
|
||||
eth_cfg = ethernetif_config_enet_set(enet_port);
|
||||
|
||||
tcpip_init(NULL, NULL);
|
||||
if (chk_lwip_bit(LWIP_INIT_FLAG)) {
|
||||
lw_print("lw: [%s] already ...\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
lw_print("lw: [%s] start ...\n", __func__);
|
||||
set_lwip_bit(LWIP_INIT_FLAG);
|
||||
|
||||
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
|
||||
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
|
||||
tcpip_init(NULL, NULL);
|
||||
|
||||
if (0 == enet_port) {
|
||||
#ifdef NETIF_ENET0_INIT_FUNC
|
||||
printf("[%s:%d] call netif_add\n", __func__, __LINE__);
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
|
||||
tcpip_input);
|
||||
#endif
|
||||
} else if (1 == enet_port) {
|
||||
#ifdef NETIF_ENET1_INIT_FUNC
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
|
||||
tcpip_input);
|
||||
#endif
|
||||
}
|
||||
|
||||
netif_set_default(&gnetif);
|
||||
netif_set_up(&gnetif);
|
||||
|
||||
lw_print("\r\n************************************************\r\n");
|
||||
lw_print(" Network Configuration\r\n");
|
||||
lw_print("************************************************\r\n");
|
||||
lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1],
|
||||
((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]);
|
||||
lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1],
|
||||
((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]);
|
||||
lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1],
|
||||
((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]);
|
||||
lw_print("************************************************\r\n");
|
||||
|
||||
lwip_config_input(&gnetif);
|
||||
}
|
||||
|
||||
|
||||
void lwip_config_net(uint8_t enet_port, char *ip, char *mask, char *gw) {
|
||||
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
||||
char* eth_cfg;
|
||||
|
||||
eth_cfg = ethernetif_config_enet_set(enet_port);
|
||||
|
||||
if(chk_lwip_bit(LWIP_INIT_FLAG)) {
|
||||
lw_print("lw: [%s] already ...\n", __func__);
|
||||
lw_print("lw: [%s] start ...\n", __func__);
|
||||
|
||||
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
|
||||
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
|
||||
|
||||
// update ip addr
|
||||
netif_set_down(&gnetif);
|
||||
netif_set_gw(&gnetif, &net_gw);
|
||||
netif_set_netmask(&gnetif, &net_netmask);
|
||||
netif_set_ipaddr(&gnetif, &net_ipaddr);
|
||||
netif_set_up(&gnetif);
|
||||
return;
|
||||
}
|
||||
set_lwip_bit(LWIP_INIT_FLAG);
|
||||
|
||||
lw_print("lw: [%s] start ...\n", __func__);
|
||||
|
||||
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
|
||||
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
|
||||
|
||||
lwip_init();
|
||||
|
||||
if(0 == enet_port) {
|
||||
if (0 == enet_port) {
|
||||
#ifdef NETIF_ENET0_INIT_FUNC
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
|
||||
ethernet_input);
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
|
||||
tcpip_input);
|
||||
#endif
|
||||
} else if (1 == enet_port) {
|
||||
} else if (1 == enet_port) {
|
||||
#ifdef NETIF_ENET1_INIT_FUNC
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
|
||||
ethernet_input);
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
|
||||
tcpip_input);
|
||||
#endif
|
||||
}
|
||||
|
||||
netif_set_default(&gnetif);
|
||||
netif_set_up(&gnetif);
|
||||
}
|
||||
|
||||
if(chk_lwip_bit(LWIP_PRINT_FLAG)) {
|
||||
lw_notice("\r\n************************************************\r\n");
|
||||
lw_notice(" Network Configuration\r\n");
|
||||
lw_notice("************************************************\r\n");
|
||||
lw_notice(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t *)&net_ipaddr)[0], ((u8_t *)&net_ipaddr)[1],
|
||||
((u8_t *)&net_ipaddr)[2], ((u8_t *)&net_ipaddr)[3]);
|
||||
lw_notice(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t *)&net_netmask)[0], ((u8_t *)&net_netmask)[1],
|
||||
((u8_t *)&net_netmask)[2], ((u8_t *)&net_netmask)[3]);
|
||||
lw_notice(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t *)&net_gw)[0], ((u8_t *)&net_gw)[1],
|
||||
((u8_t *)&net_gw)[2], ((u8_t *)&net_gw)[3]);
|
||||
lw_notice("************************************************\r\n");
|
||||
}
|
||||
lwip_config_input(&gnetif);
|
||||
netif_set_default(&gnetif);
|
||||
netif_set_up(&gnetif);
|
||||
|
||||
lw_print("\r\n************************************************\r\n");
|
||||
lw_print(" Network Configuration\r\n");
|
||||
lw_print("************************************************\r\n");
|
||||
lw_print(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1],
|
||||
((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]);
|
||||
lw_print(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1],
|
||||
((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]);
|
||||
lw_print(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1],
|
||||
((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]);
|
||||
lw_print("************************************************\r\n");
|
||||
|
||||
lwip_config_input(&gnetif);
|
||||
}
|
||||
|
||||
void lwip_config_net(uint8_t enet_port, char* ip, char* mask, char* gw)
|
||||
{
|
||||
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
||||
char* eth_cfg;
|
||||
|
||||
eth_cfg = ethernetif_config_enet_set(enet_port);
|
||||
|
||||
if (chk_lwip_bit(LWIP_INIT_FLAG)) {
|
||||
lw_print("lw: [%s] already ...\n", __func__);
|
||||
|
||||
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
|
||||
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
|
||||
|
||||
// update ip addr
|
||||
netif_set_down(&gnetif);
|
||||
netif_set_gw(&gnetif, &net_gw);
|
||||
netif_set_netmask(&gnetif, &net_netmask);
|
||||
netif_set_ipaddr(&gnetif, &net_ipaddr);
|
||||
netif_set_up(&gnetif);
|
||||
return;
|
||||
}
|
||||
set_lwip_bit(LWIP_INIT_FLAG);
|
||||
|
||||
lw_print("lw: [%s] start ...\n", __func__);
|
||||
|
||||
IP4_ADDR(&net_ipaddr, ip[0], ip[1], ip[2], ip[3]);
|
||||
IP4_ADDR(&net_netmask, mask[0], mask[1], mask[2], mask[3]);
|
||||
IP4_ADDR(&net_gw, gw[0], gw[1], gw[2], gw[3]);
|
||||
|
||||
lwip_init();
|
||||
|
||||
if (0 == enet_port) {
|
||||
#ifdef NETIF_ENET0_INIT_FUNC
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
|
||||
ethernet_input);
|
||||
#endif
|
||||
} else if (1 == enet_port) {
|
||||
#ifdef NETIF_ENET1_INIT_FUNC
|
||||
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET1_INIT_FUNC,
|
||||
ethernet_input);
|
||||
#endif
|
||||
}
|
||||
|
||||
netif_set_default(&gnetif);
|
||||
netif_set_up(&gnetif);
|
||||
|
||||
if (chk_lwip_bit(LWIP_PRINT_FLAG)) {
|
||||
lw_notice("\r\n************************************************\r\n");
|
||||
lw_notice(" Network Configuration\r\n");
|
||||
lw_notice("************************************************\r\n");
|
||||
lw_notice(" IPv4 Address : %u.%u.%u.%u\r\n", ((u8_t*)&net_ipaddr)[0], ((u8_t*)&net_ipaddr)[1],
|
||||
((u8_t*)&net_ipaddr)[2], ((u8_t*)&net_ipaddr)[3]);
|
||||
lw_notice(" IPv4 Subnet mask : %u.%u.%u.%u\r\n", ((u8_t*)&net_netmask)[0], ((u8_t*)&net_netmask)[1],
|
||||
((u8_t*)&net_netmask)[2], ((u8_t*)&net_netmask)[3]);
|
||||
lw_notice(" IPv4 Gateway : %u.%u.%u.%u\r\n", ((u8_t*)&net_gw)[0], ((u8_t*)&net_gw)[1],
|
||||
((u8_t*)&net_gw)[2], ((u8_t*)&net_gw)[3]);
|
||||
lw_notice("************************************************\r\n");
|
||||
}
|
||||
lwip_config_input(&gnetif);
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
|
|||
*rp++ = '.';
|
||||
ap++;
|
||||
}
|
||||
*--rp = 0;
|
||||
*--rp = '\0';
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_DIR += cmd_lwip
|
||||
SRC_DIR += cmd_lwip netdev
|
||||
LWIP_DIR := LwIP
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c
|
||||
SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c http_test.c
|
||||
# SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
|
|
|
@ -50,7 +50,7 @@ static void iperf_udp_client(void *thread_param)
|
|||
send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ;
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0){
|
||||
if(sock < 0) {
|
||||
KPrintf("[%s:%d] can't create socket! exit!\n", __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
|
@ -60,21 +60,21 @@ static void iperf_udp_client(void *thread_param)
|
|||
server.sin_addr.s_addr = inet_addr(param.host);
|
||||
memset(&(server.sin_zero), 0, sizeof(server.sin_zero));
|
||||
|
||||
if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))){
|
||||
if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))) {
|
||||
lw_error("Unable to connect\n");
|
||||
closesocket(sock);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = malloc(IPERF_BUFSZ);
|
||||
if (buffer == NULL){
|
||||
if (buffer == NULL) {
|
||||
printf("[%s:%d] malloc failed\n", __FILE__, __LINE__);
|
||||
return;
|
||||
}
|
||||
memset(buffer, 0x00, IPERF_BUFSZ);
|
||||
|
||||
KPrintf("iperf udp mode run...\n");
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
packet_count++;
|
||||
tick = CurrentTicksGain();
|
||||
buffer[0] = htonl(packet_count);
|
||||
|
@ -101,12 +101,12 @@ static void iperf_udp_server(void *thread_param)
|
|||
struct timeval timeout;
|
||||
|
||||
buffer = malloc(IPERF_BUFSZ);
|
||||
if (buffer == NULL){
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
sock = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if(sock < 0){
|
||||
if(sock < 0) {
|
||||
KPrintf("can't create socket! exit!");
|
||||
return;
|
||||
}
|
||||
|
@ -117,35 +117,34 @@ static void iperf_udp_server(void *thread_param)
|
|||
|
||||
timeout.tv_sec = 2;
|
||||
timeout.tv_usec = 0;
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1){
|
||||
if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {
|
||||
KPrintf("setsockopt failed!");
|
||||
closesocket(sock);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0){
|
||||
if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0) {
|
||||
KPrintf("iperf server bind failed! exit!");
|
||||
closesocket(sock);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
tick1 = CurrentTicksGain();
|
||||
tick2 = tick1;
|
||||
lost = 0;
|
||||
total = 0;
|
||||
sentlen = 0;
|
||||
while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){
|
||||
while ((tick2 - tick1) < (TICK_PER_SECOND * 5)) {
|
||||
r_size = recvfrom(sock, buffer, IPERF_BUFSZ, 0, (struct sockaddr *)&sender, (socklen_t*)&sender_len);
|
||||
if (r_size > 12){
|
||||
if (r_size > 12) {
|
||||
pcount = ntohl(buffer[0]);
|
||||
if (last_pcount < pcount){
|
||||
if (last_pcount < pcount) {
|
||||
lost += pcount - last_pcount - 1;
|
||||
total += pcount - last_pcount;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
last_pcount = pcount;
|
||||
}
|
||||
last_pcount = pcount;
|
||||
|
@ -153,7 +152,7 @@ static void iperf_udp_server(void *thread_param)
|
|||
}
|
||||
tick2 = CurrentTicksGain();
|
||||
}
|
||||
if (sentlen > 0){
|
||||
if (sentlen > 0) {
|
||||
long data;
|
||||
int integer, decimal;
|
||||
KTaskDescriptorType tid;
|
||||
|
@ -186,10 +185,9 @@ static void iperf_client(void *thread_param)
|
|||
for (i = 0; i < IPERF_BUFSZ; i ++)
|
||||
send_buf[i] = i & 0xff;
|
||||
|
||||
while (param.mode != IPERF_MODE_STOP)
|
||||
{
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0){
|
||||
if (sock < 0) {
|
||||
KPrintf("create socket failed!");
|
||||
DelayKTask(TICK_PER_SECOND);
|
||||
continue;
|
||||
|
@ -200,8 +198,8 @@ static void iperf_client(void *thread_param)
|
|||
addr.sin_addr.s_addr = inet_addr((char *)param.host);
|
||||
|
||||
ret = connect(sock, (const struct sockaddr *)&addr, sizeof(addr));
|
||||
if (ret == -1){
|
||||
if (tips){
|
||||
if (ret == -1) {
|
||||
if (tips) {
|
||||
KPrintf("Connect to iperf server faile, Waiting for the server to open!");
|
||||
tips = 0;
|
||||
}
|
||||
|
@ -224,9 +222,9 @@ static void iperf_client(void *thread_param)
|
|||
sentlen = 0;
|
||||
|
||||
tick1 = CurrentTicksGain();
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
tick2 = CurrentTicksGain();
|
||||
if (tick2 - tick1 >= TICK_PER_SECOND * 5){
|
||||
if (tick2 - tick1 >= TICK_PER_SECOND * 5) {
|
||||
double speed;
|
||||
// int integer, decimal;
|
||||
KTaskDescriptorType tid;
|
||||
|
@ -240,7 +238,7 @@ static void iperf_client(void *thread_param)
|
|||
}
|
||||
|
||||
ret = send(sock, send_buf, IPERF_BUFSZ, 0);
|
||||
if (ret > 0){
|
||||
if (ret > 0) {
|
||||
sentlen += ret;
|
||||
}
|
||||
|
||||
|
@ -264,7 +262,7 @@ struct sock_conn_cb {
|
|||
int parent_id;
|
||||
};
|
||||
|
||||
void iperf_sever_worker(void* arg) {
|
||||
void iperf_server_worker(void* arg) {
|
||||
struct sock_conn_cb *sccb = (struct sock_conn_cb *)arg;
|
||||
x_ticks_t tick1, tick2;
|
||||
|
||||
|
@ -287,7 +285,7 @@ void iperf_sever_worker(void* arg) {
|
|||
int cur_tid = GetKTaskDescriptor()->id.id;
|
||||
|
||||
tick1 = CurrentTicksGain();
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
bytes_received = recv(sccb->connected, recv_data, IPERF_BUFSZ, 0);
|
||||
if (bytes_received == 0) {
|
||||
KPrintf("client disconnected (%s, %d)\n",
|
||||
|
@ -336,7 +334,7 @@ void iperf_server_multithread(void *thread_param)
|
|||
struct timeval timeout;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0){
|
||||
if (sock < 0) {
|
||||
KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__);
|
||||
goto __exit;
|
||||
}
|
||||
|
@ -346,12 +344,12 @@ void iperf_server_multithread(void *thread_param)
|
|||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero));
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){
|
||||
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
|
||||
KPrintf("Unable to bind!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (listen(sock, 5) == -1){
|
||||
if (listen(sock, 5) == -1) {
|
||||
KPrintf("Listen error!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
@ -360,7 +358,7 @@ void iperf_server_multithread(void *thread_param)
|
|||
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(sock, &readset);
|
||||
|
||||
|
@ -379,8 +377,8 @@ void iperf_server_multithread(void *thread_param)
|
|||
sccb->client_addr = client_addr;
|
||||
sccb->server_addr = server_addr;
|
||||
sccb->parent_id = cur_tid;
|
||||
int tid = KTaskCreate("iperf server", iperf_sever_worker, sccb, LWIP_TASK_STACK_SIZE, 20);
|
||||
// iperf_sever_worker(sccb);
|
||||
int tid = KTaskCreate("iperf server", iperf_server_worker, sccb, LWIP_TASK_STACK_SIZE, 20);
|
||||
// iperf_server_worker(sccb);
|
||||
if (tid) {
|
||||
StartupKTask(tid);
|
||||
} else {
|
||||
|
@ -405,13 +403,13 @@ void iperf_server(void *thread_param)
|
|||
struct timeval timeout;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0){
|
||||
if (sock < 0) {
|
||||
KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__);
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
recv_data = (uint8_t *)malloc(IPERF_BUFSZ);
|
||||
if (recv_data == NULL){
|
||||
if (recv_data == NULL) {
|
||||
KPrintf("No memory!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
@ -421,12 +419,12 @@ void iperf_server(void *thread_param)
|
|||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero));
|
||||
|
||||
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){
|
||||
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) {
|
||||
KPrintf("Unable to bind!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (listen(sock, 5) == -1){
|
||||
if (listen(sock, 5) == -1) {
|
||||
KPrintf("Listen error!\n");
|
||||
goto __exit;
|
||||
}
|
||||
|
@ -434,7 +432,7 @@ void iperf_server(void *thread_param)
|
|||
timeout.tv_sec = 3;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(sock, &readset);
|
||||
|
||||
|
@ -458,7 +456,7 @@ void iperf_server(void *thread_param)
|
|||
|
||||
recvlen = 0;
|
||||
tick1 = CurrentTicksGain();
|
||||
while (param.mode != IPERF_MODE_STOP){
|
||||
while (param.mode != IPERF_MODE_STOP) {
|
||||
bytes_received = recv(connected, recv_data, IPERF_BUFSZ, 0);
|
||||
if (bytes_received == 0) {
|
||||
KPrintf("client disconnected (%s, %d)\n",
|
||||
|
@ -526,48 +524,37 @@ int iperf(int argc, char **argv)
|
|||
int use_udp = 0;
|
||||
int index = 1;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (argc == 1) {
|
||||
goto __usage;
|
||||
}
|
||||
if (strcmp(argv[1], "-u") == 0)
|
||||
{
|
||||
if (strcmp(argv[1], "-u") == 0) {
|
||||
index = 2;
|
||||
use_udp = 1;
|
||||
}
|
||||
if (strcmp(argv[index], "-h") == 0) goto __usage;
|
||||
else if (strcmp(argv[index], "--stop") == 0)
|
||||
{
|
||||
else if (strcmp(argv[index], "--stop") == 0) {
|
||||
/* stop iperf */
|
||||
param.mode = IPERF_MODE_STOP;
|
||||
printf("iperf stop.\n");
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp(argv[index], "-s") == 0)
|
||||
{
|
||||
} else if (strcmp(argv[index], "-s") == 0) {
|
||||
mode = IPERF_MODE_SERVER; /* server mode */
|
||||
|
||||
/* iperf -s -p 5000 */
|
||||
if (argc >= 4)
|
||||
{
|
||||
if (strcmp(argv[index + 1], "-p") == 0)
|
||||
{
|
||||
if (argc >= 4) {
|
||||
if (strcmp(argv[index + 1], "-p") == 0) {
|
||||
port = atoi(argv[index + 2]);
|
||||
}
|
||||
else goto __usage;
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[index], "-c") == 0)
|
||||
{
|
||||
} else if (strcmp(argv[index], "-c") == 0) {
|
||||
mode = IPERF_MODE_CLIENT; /* client mode */
|
||||
if (argc < 3) goto __usage;
|
||||
|
||||
host = argv[index + 1];
|
||||
if (argc >= 5)
|
||||
{
|
||||
if (argc >= 5) {
|
||||
/* iperf -c host -p port */
|
||||
if (strcmp(argv[index + 2], "-p") == 0)
|
||||
{
|
||||
if (strcmp(argv[index + 2], "-p") == 0) {
|
||||
port = atoi(argv[index + 3]);
|
||||
}
|
||||
else goto __usage;
|
||||
|
@ -575,57 +562,43 @@ int iperf(int argc, char **argv)
|
|||
}
|
||||
else goto __usage;
|
||||
|
||||
if (argc >= 7)
|
||||
{
|
||||
if(strcmp(argv[argc - 2], "-m") == 0)
|
||||
{
|
||||
if (argc >= 7) {
|
||||
if(strcmp(argv[argc - 2], "-m") == 0) {
|
||||
numtid = atoi(argv[argc - 1]);
|
||||
}
|
||||
else goto __usage;
|
||||
}
|
||||
|
||||
/* start iperf */
|
||||
if (param.mode == IPERF_MODE_STOP)
|
||||
{
|
||||
if (param.mode == IPERF_MODE_STOP) {
|
||||
int i = 0;
|
||||
char tid_name[NAME_NUM_MAX + 1] = {0};
|
||||
|
||||
param.mode = mode;
|
||||
param.port = port;
|
||||
if (param.host)
|
||||
{
|
||||
if (param.host) {
|
||||
free(param.host);
|
||||
param.host = NULL;
|
||||
}
|
||||
if (host) param.host = strdup(host);
|
||||
|
||||
for (i = 0; i < numtid; i++)
|
||||
{
|
||||
for (i = 0; i < numtid; i++) {
|
||||
int32 tid = 0;
|
||||
void (*function)(void *parameter);
|
||||
|
||||
if (use_udp)
|
||||
{
|
||||
if (mode == IPERF_MODE_CLIENT)
|
||||
{
|
||||
if (use_udp) {
|
||||
if (mode == IPERF_MODE_CLIENT) {
|
||||
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
|
||||
function = iperf_udp_client;
|
||||
}
|
||||
else if (mode == IPERF_MODE_SERVER)
|
||||
{
|
||||
} else if (mode == IPERF_MODE_SERVER) {
|
||||
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
|
||||
function = iperf_udp_server;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mode == IPERF_MODE_CLIENT)
|
||||
{
|
||||
} else {
|
||||
if (mode == IPERF_MODE_CLIENT) {
|
||||
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
|
||||
function = iperf_client;
|
||||
}
|
||||
else if (mode == IPERF_MODE_SERVER)
|
||||
{
|
||||
} else if (mode == IPERF_MODE_SERVER) {
|
||||
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
|
||||
function = iperf_server_multithread;
|
||||
}
|
||||
|
@ -634,9 +607,7 @@ int iperf(int argc, char **argv)
|
|||
tid = KTaskCreate(tid_name, function, NULL, LWIP_TASK_STACK_SIZE, 20);
|
||||
if (tid) StartupKTask(tid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
KPrintf("Please stop iperf firstly, by:\n");
|
||||
KPrintf("iperf --stop\n");
|
||||
}
|
||||
|
|