forked from xuos/xiuos
Merge branch 'prepare_for_master' of https://gitlink.org.cn/xuos/xiuos into mqtt
This commit is contained in:
commit
34e855a3a9
|
@ -72,6 +72,24 @@ menu "test app"
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
menuconfig USER_TEST_SOCKET
|
||||||
|
select BSP_USING_LWIP
|
||||||
|
bool "Config test socket(lwip)"
|
||||||
|
default n
|
||||||
|
|
||||||
|
menuconfig USER_TEST_UART
|
||||||
|
select BSP_USING_UART
|
||||||
|
select BSP_USING_UART6
|
||||||
|
bool "Config test uart"
|
||||||
|
default n
|
||||||
|
if USER_TEST_UART
|
||||||
|
if ADD_XIZI_FEATURES
|
||||||
|
config UART_DEV_DRIVER
|
||||||
|
string "Set uart dev path"
|
||||||
|
default "/dev/usart6_dev6"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
menuconfig USER_TEST_RS485
|
menuconfig USER_TEST_RS485
|
||||||
select BSP_USING_UART
|
select BSP_USING_UART
|
||||||
select BSP_USING_GPIO
|
select BSP_USING_GPIO
|
||||||
|
|
|
@ -49,6 +49,10 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES += test_i2c.c
|
SRC_FILES += test_i2c.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_UART),y)
|
||||||
|
SRC_FILES += test_uart.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_GPIO),y)
|
ifeq ($(CONFIG_USER_TEST_GPIO),y)
|
||||||
SRC_FILES += test_gpio.c
|
SRC_FILES += test_gpio.c
|
||||||
endif
|
endif
|
||||||
|
@ -113,6 +117,10 @@ ifeq ($(CONFIG_ADD_XIZI_FEATURES),y)
|
||||||
SRC_FILES += test_rbtree/test_rbtree.c
|
SRC_FILES += test_rbtree/test_rbtree.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_USER_TEST_SOCKET),y)
|
||||||
|
SRC_FILES += test_socket.c
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_USER_TEST_WEBSERVER),y)
|
ifeq ($(CONFIG_USER_TEST_WEBSERVER),y)
|
||||||
SRC_FILES +=
|
SRC_FILES +=
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -26,9 +26,8 @@
|
||||||
void TestAdc(void)
|
void TestAdc(void)
|
||||||
{
|
{
|
||||||
int adc_fd;
|
int adc_fd;
|
||||||
uint8 adc_channel = 0x0;
|
uint8 adc_channel = 0x1;
|
||||||
uint16 adc_sample, adc_value_decimal = 0;
|
uint16 adc_sample = 0;
|
||||||
float adc_value;
|
|
||||||
|
|
||||||
adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR);
|
adc_fd = PrivOpen(ADC_DEV_DRIVER, O_RDWR);
|
||||||
if (adc_fd < 0) {
|
if (adc_fd < 0) {
|
||||||
|
@ -45,13 +44,11 @@ void TestAdc(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
PrivRead(adc_fd, &adc_sample, 2);
|
PrivRead(adc_fd, &adc_sample, 2);
|
||||||
|
printf("adc sample %u mv\n", adc_sample);
|
||||||
adc_value = (float)adc_sample * (3.3 / 4096);
|
PrivTaskDelay(500);
|
||||||
|
}
|
||||||
adc_value_decimal = (adc_value - (uint16)adc_value) * 1000;
|
|
||||||
|
|
||||||
printf("adc sample %u value integer %u decimal %u\n", adc_sample, (uint16)adc_value, adc_value_decimal);
|
|
||||||
|
|
||||||
PrivClose(adc_fd);
|
PrivClose(adc_fd);
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,16 @@
|
||||||
#include <transform.h>
|
#include <transform.h>
|
||||||
#ifdef ADD_XIZI_FEATURES
|
#ifdef ADD_XIZI_FEATURES
|
||||||
|
|
||||||
void TestDac(void)
|
static pthread_t test_dac_task;
|
||||||
|
|
||||||
|
static void *TestDacTask(void *parameter)
|
||||||
{
|
{
|
||||||
int dac_fd;
|
int dac_fd;
|
||||||
uint16 dac_set_value = 800;
|
uint16 dac_set_value = 4096 * 10;//sin length
|
||||||
uint16 dac_sample, dac_value_decimal = 0;
|
|
||||||
float dac_value;
|
|
||||||
|
|
||||||
dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR);
|
dac_fd = PrivOpen(DAC_DEV_DRIVER, O_RDWR);
|
||||||
if (dac_fd < 0) {
|
if (dac_fd < 0) {
|
||||||
KPrintf("open dac fd error %d\n", dac_fd);
|
KPrintf("open dac fd error %d\n", dac_fd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PrivIoctlCfg ioctl_cfg;
|
struct PrivIoctlCfg ioctl_cfg;
|
||||||
|
@ -41,20 +40,24 @@ void TestDac(void)
|
||||||
if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) {
|
if (0 != PrivIoctl(dac_fd, OPE_CFG, &ioctl_cfg)) {
|
||||||
KPrintf("ioctl dac fd error %d\n", dac_fd);
|
KPrintf("ioctl dac fd error %d\n", dac_fd);
|
||||||
PrivClose(dac_fd);
|
PrivClose(dac_fd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivRead(dac_fd, &dac_sample, 2);
|
while (1) {
|
||||||
|
//start dac output sin
|
||||||
dac_value = (float)dac_sample * (3.3 / 4096);//Vref+ need to be 3.3V
|
PrivWrite(dac_fd, NULL, 0);
|
||||||
|
}
|
||||||
dac_value_decimal = (dac_value - (uint16)dac_value) * 1000;
|
|
||||||
|
|
||||||
printf("dac sample %u value integer %u decimal %u\n", dac_sample, (uint16)dac_value, dac_value_decimal);
|
|
||||||
|
|
||||||
PrivClose(dac_fd);
|
PrivClose(dac_fd);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
void TestDac(void)
|
||||||
|
{
|
||||||
|
pthread_attr_t tid;
|
||||||
|
tid.schedparam.sched_priority = 20;
|
||||||
|
tid.stacksize = 4096;
|
||||||
|
|
||||||
|
PrivTaskCreate(&test_dac_task, &tid, &TestDacTask, NULL);
|
||||||
|
PrivTaskStartup(&test_dac_task);
|
||||||
}
|
}
|
||||||
PRIV_SHELL_CMD_FUNCTION(TestDac, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
PRIV_SHELL_CMD_FUNCTION(TestDac, a dac test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
#endif
|
#endif
|
|
@ -28,7 +28,7 @@
|
||||||
static uint16_t pin_fd=0;
|
static uint16_t pin_fd=0;
|
||||||
static struct PinStat pin_led;
|
static struct PinStat pin_led;
|
||||||
|
|
||||||
void ledflip(void *parameter)
|
void LedFlip(void *parameter)
|
||||||
{
|
{
|
||||||
pin_led.pin = BSP_LED_PIN;
|
pin_led.pin = BSP_LED_PIN;
|
||||||
pin_led.val = !pin_led.val;
|
pin_led.val = !pin_led.val;
|
||||||
|
@ -68,7 +68,7 @@ void TestHwTimer(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl_cfg.ioctl_driver_type = TIME_TYPE;
|
ioctl_cfg.ioctl_driver_type = TIME_TYPE;
|
||||||
ioctl_cfg.args = (void *)&ledflip;
|
ioctl_cfg.args = (void *)&LedFlip;
|
||||||
if (0 != PrivIoctl(timer_fd, OPE_INT, &ioctl_cfg)) {
|
if (0 != PrivIoctl(timer_fd, OPE_INT, &ioctl_cfg)) {
|
||||||
printf("timer pin fd error %d\n", pin_fd);
|
printf("timer pin fd error %d\n", pin_fd);
|
||||||
PrivClose(pin_fd);
|
PrivClose(pin_fd);
|
||||||
|
@ -86,9 +86,6 @@ void TestHwTimer(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// int32 timer_handle = KCreateTimer("LED on and off by 1s",&ledflip,&pin_fd,period,TIMER_TRIGGER_PERIODIC);
|
|
||||||
|
|
||||||
// KTimerStartRun(timer_handle);
|
|
||||||
PrivClose(pin_fd);
|
PrivClose(pin_fd);
|
||||||
PrivClose(timer_fd);
|
PrivClose(timer_fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,16 @@
|
||||||
|
|
||||||
#define I2C_SLAVE_ADDRESS 0x0012U
|
#define I2C_SLAVE_ADDRESS 0x0012U
|
||||||
|
|
||||||
void TestI2C(void)
|
int OpenIic(void)
|
||||||
{
|
{
|
||||||
// config IIC pin(SCL:34.SDA:35) in menuconfig
|
|
||||||
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
|
int iic_fd = PrivOpen(I2C_DEV_DRIVER, O_RDWR);
|
||||||
if (iic_fd < 0)
|
if (iic_fd < 0)
|
||||||
{
|
{
|
||||||
printf("open iic_fd fd error:%d\n", iic_fd);
|
printf("[TestI2C] Open iic_fd fd error: %d\n", iic_fd);
|
||||||
return;
|
return -ERROR;
|
||||||
}
|
}
|
||||||
printf("IIC open successful!\n");
|
printf("[TestI2C] IIC open successful!\n");
|
||||||
|
|
||||||
// init iic
|
|
||||||
uint16 iic_address = I2C_SLAVE_ADDRESS;
|
uint16 iic_address = I2C_SLAVE_ADDRESS;
|
||||||
|
|
||||||
struct PrivIoctlCfg ioctl_cfg;
|
struct PrivIoctlCfg ioctl_cfg;
|
||||||
|
@ -44,28 +42,55 @@ void TestI2C(void)
|
||||||
|
|
||||||
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
|
if (0 != PrivIoctl(iic_fd, OPE_INT, &ioctl_cfg))
|
||||||
{
|
{
|
||||||
printf("ioctl iic fd error %d\n", iic_fd);
|
printf("[TestI2C] Ioctl iic fd error %d\n", iic_fd);
|
||||||
PrivClose(iic_fd);
|
PrivClose(iic_fd);
|
||||||
return;
|
return -ERROR;
|
||||||
}
|
}
|
||||||
printf("IIC configure successful!\n");
|
printf("IIC configure successful!\n");
|
||||||
|
|
||||||
// I2C read and write
|
return iic_fd;
|
||||||
char tmp_buff[100];
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
PrivTaskDelay(1000);
|
|
||||||
PrivWrite(iic_fd, "Hello World!\n", sizeof("Hello World!\n"));
|
|
||||||
printf("msg send:%s\n", "Hello World!\n");
|
|
||||||
PrivTaskDelay(1000);
|
|
||||||
memset(tmp_buff, 0, sizeof(tmp_buff));
|
|
||||||
PrivRead(iic_fd, tmp_buff, sizeof(tmp_buff));
|
|
||||||
printf("msg recv:%s\n", tmp_buff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivClose(iic_fd);
|
static const int nr_transmit = 15;
|
||||||
|
|
||||||
|
void TestMasterI2c(void)
|
||||||
|
{
|
||||||
|
char recv_buff[13] = { 0 };
|
||||||
|
|
||||||
|
int iic_fd = OpenIic();
|
||||||
|
if (iic_fd < 0) {
|
||||||
|
printf("[%s] Error open iic\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIV_SHELL_CMD_FUNCTION(TestI2C, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) {
|
||||||
|
// wait if you like.
|
||||||
|
PrivTaskDelay(500);
|
||||||
|
memset(recv_buff, 0, sizeof(recv_buff));
|
||||||
|
PrivRead(iic_fd, recv_buff, sizeof(recv_buff));
|
||||||
|
printf("[%s] Msg recv: %s\n", __func__, recv_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivClose(iic_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestSlaveI2c(void)
|
||||||
|
{
|
||||||
|
char send_buff[] = "Hello, World";
|
||||||
|
|
||||||
|
int iic_fd = OpenIic();
|
||||||
|
|
||||||
|
for (int transmit_cnt = 0; transmit_cnt < nr_transmit; transmit_cnt++) {
|
||||||
|
// wait if you like.
|
||||||
|
PrivTaskDelay(500);
|
||||||
|
PrivWrite(iic_fd, send_buff, sizeof(send_buff));
|
||||||
|
printf("[%s] Msg send: %s\n", __func__, send_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivClose(iic_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(TestMasterI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
|
PRIV_SHELL_CMD_FUNCTION(TestSlaveI2c, a iic test sample, PRIV_SHELL_CMD_MAIN_ATTR);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -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
|
|
@ -1,7 +1,4 @@
|
||||||
menuconfig BSP_USING_ADC1
|
if BSP_USING_ADC
|
||||||
bool "Enable ADC1"
|
|
||||||
default y
|
|
||||||
if BSP_USING_ADC1
|
|
||||||
config ADC1_BUS_NAME
|
config ADC1_BUS_NAME
|
||||||
string "adc 1 bus name"
|
string "adc 1 bus name"
|
||||||
default "adc1"
|
default "adc1"
|
||||||
|
@ -13,62 +10,4 @@ menuconfig BSP_USING_ADC1
|
||||||
config ADC1_DEVICE_NAME
|
config ADC1_DEVICE_NAME
|
||||||
string "adc 1 bus device name"
|
string "adc 1 bus device name"
|
||||||
default "adc1_dev"
|
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
|
endif
|
||||||
|
|
|
@ -20,79 +20,251 @@
|
||||||
|
|
||||||
#include <connect_adc.h>
|
#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
|
/* The clock source of ADC. */
|
||||||
#define ADC1_GPIO ADC_CONS(GPIO_Pin_, ADC1_GPIO_NUM)
|
#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
|
#endif
|
||||||
|
|
||||||
#ifdef BSP_USING_ADC2
|
/* ADC unit instance for this example. */
|
||||||
#define ADC2_GPIO ADC_CONS(GPIO_Pin_, ADC2_GPIO_NUM)
|
#define ADC_UNIT (CM_ADC1)
|
||||||
#endif
|
#define ADC_PERIPH_CLK (FCG3_PERIPH_ADC1)
|
||||||
|
|
||||||
#ifdef BSP_USING_ADC3
|
/* Selects ADC channels that needed. */
|
||||||
#define ADC3_GPIO ADC_CONS(GPIO_Pin_, ADC3_GPIO_NUM)
|
#define ADC_CH_POTENTIOMETER (ADC_CH3)
|
||||||
#endif
|
#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;
|
stc_gpio_init_t stcGpioInit;
|
||||||
uint32 told, tnow, tcnt = 0;
|
|
||||||
uint32 reload = SysTick->LOAD;
|
|
||||||
|
|
||||||
ticks = us * reload / (1000000 / TICK_PER_SECOND);
|
(void)GPIO_StructInit(&stcGpioInit);
|
||||||
told = SysTick->VAL;
|
stcGpioInit.u16PinAttr = PIN_ATTR_ANALOG;
|
||||||
while (1) {
|
(void)GPIO_Init(ADC_CH_PORT, ADC_CH_PIN, &stcGpioInit);
|
||||||
tnow = SysTick->VAL;
|
|
||||||
if (tnow != told) {
|
|
||||||
if (tnow < told) {
|
|
||||||
tcnt += told - tnow;
|
|
||||||
} else {
|
|
||||||
tcnt += reload - tnow + told;
|
|
||||||
}
|
}
|
||||||
told = tnow;
|
|
||||||
if (tcnt >= ticks) {
|
/**
|
||||||
return 0;
|
* @brief Configures ADC clock.
|
||||||
|
* @param None
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
static void AdcClockConfig(void)
|
||||||
|
{
|
||||||
|
#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));
|
||||||
|
|
||||||
|
#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;
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16 GetAdcAverageValue(CM_ADC_TypeDef *ADCx, uint8 channel, uint8 times)
|
return ADC_CAL_VOL(u16AdcValue);
|
||||||
{
|
|
||||||
uint32 temp_val = 0;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 AdcOpen(void *dev)
|
static uint32 AdcOpen(void *dev)
|
||||||
{
|
{
|
||||||
x_err_t ret = EOK;
|
x_err_t ret = EOK;
|
||||||
stc_adc_init_t stcAdcInit;
|
|
||||||
ADC_StructInit(&stcAdcInit);
|
|
||||||
struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32 AdcClose(void *dev)
|
static uint32 AdcClose(void *dev)
|
||||||
{
|
{
|
||||||
// CM_ADC_TypeDef *adc_dev = (CM_ADC_TypeDef*)dev;
|
|
||||||
struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev;
|
struct AdcHardwareDevice* adc_dev = (struct AdcHardwareDevice*)dev;
|
||||||
|
|
||||||
CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data;
|
CM_ADC_TypeDef *ADCx= (CM_ADC_TypeDef *)adc_dev->private_data;
|
||||||
|
|
||||||
|
ADC_Stop(ADC_UNIT);
|
||||||
ADC_DeInit(ADCx);
|
ADC_DeInit(ADCx);
|
||||||
|
|
||||||
return EOK;
|
return EOK;
|
||||||
|
@ -100,19 +272,10 @@ static uint32 AdcClose(void *dev)
|
||||||
|
|
||||||
static uint32 AdcRead(void *dev, struct BusBlockReadParam *read_param)
|
static uint32 AdcRead(void *dev, struct BusBlockReadParam *read_param)
|
||||||
{
|
{
|
||||||
struct AdcHardwareDevice *adc_dev = (struct AdcHardwareDevice *)dev;
|
*(uint16 *)read_param->buffer = AdcPolling();
|
||||||
|
|
||||||
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;
|
read_param->read_length = 2;
|
||||||
|
|
||||||
return read_param->read_length;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32 AdcDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
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:
|
case OPE_CFG:
|
||||||
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
|
adc_cfg->adc_channel = *(uint8 *)configure_info->private_data;
|
||||||
if (adc_cfg->adc_channel > 18) {
|
if (adc_cfg->adc_channel != 1) {
|
||||||
KPrintf("AdcDrvConfigure set adc channel(0-18) %u error!", adc_cfg->adc_channel);
|
KPrintf("AdcDrvConfigure set adc channel(1) %u error!", adc_cfg->adc_channel);
|
||||||
adc_cfg->adc_channel = 0;
|
adc_cfg->adc_channel = 1;
|
||||||
ret = ERROR;
|
ret = ERROR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -156,7 +319,7 @@ int HwAdcInit(void)
|
||||||
{
|
{
|
||||||
x_err_t ret = EOK;
|
x_err_t ret = EOK;
|
||||||
|
|
||||||
#ifdef BSP_USING_ADC1
|
#ifdef BSP_USING_ADC
|
||||||
static struct AdcBus adc1_bus;
|
static struct AdcBus adc1_bus;
|
||||||
static struct AdcDriver adc1_drv;
|
static struct AdcDriver adc1_drv;
|
||||||
static struct AdcHardwareDevice adc1_dev;
|
static struct AdcHardwareDevice adc1_dev;
|
||||||
|
@ -183,7 +346,7 @@ int HwAdcInit(void)
|
||||||
|
|
||||||
adc1_dev.adc_dev_done = &dev_done;
|
adc1_dev.adc_dev_done = &dev_done;
|
||||||
adc1_cfg.ADCx = CM_ADC1;
|
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);
|
ret = AdcDeviceRegister(&adc1_dev, (void *)&adc1_cfg, ADC1_DEVICE_NAME);
|
||||||
if (ret != EOK) {
|
if (ret != EOK) {
|
||||||
|
@ -197,88 +360,6 @@ int HwAdcInit(void)
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ ifeq ($(CONFIG_BSP_USING_ADC),y)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_BSP_USING_DAC),y)
|
ifeq ($(CONFIG_BSP_USING_DAC),y)
|
||||||
SRC_FILES += hc32_ll_dac.c
|
SRC_FILES += hc32_ll_dac.c hc32_ll_mau.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_BSP_USING_SDIO),y)
|
ifeq ($(CONFIG_BSP_USING_SDIO),y)
|
||||||
|
|
|
@ -20,56 +20,301 @@
|
||||||
|
|
||||||
#include <connect_dac.h>
|
#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 VREFH (3.3F)
|
||||||
#define DAC_GPIO DAC_CONS(GPIO_Pin_, DAC_GPIO_NUM)
|
#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
|
#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)
|
static uint32 DacOpen(void *dev)
|
||||||
{
|
{
|
||||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)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;
|
/* Init single DAC */
|
||||||
|
pSingleDac = DacSingleConversionInit(DAC_Unit1);
|
||||||
DAC_StructInit(&pstcDacInit);
|
|
||||||
|
|
||||||
DAC_Init(DACx,DAC_CH1,&pstcDacInit);
|
|
||||||
|
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32 DacClose(void *dev)
|
static uint32 DacClose(void *dev)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
||||||
|
|
||||||
CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data;
|
CM_DAC_TypeDef *DACx = (CM_DAC_TypeDef *)dac_dev->private_data;
|
||||||
|
|
||||||
|
DAC_StopConversion(pSingleDac);
|
||||||
|
|
||||||
DAC_DeInit(DACx);
|
DAC_DeInit(DACx);
|
||||||
|
|
||||||
|
MauDeinit();
|
||||||
|
|
||||||
|
memset(gu32SinTable, 0 , sizeof(gu32SinTable));
|
||||||
|
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32 DacWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||||
static uint32 DacRead(void *dev, struct BusBlockReadParam *read_param)
|
|
||||||
{
|
{
|
||||||
struct DacHardwareDevice *dac_dev = (struct DacHardwareDevice *)dev;
|
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;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,8 +333,6 @@ static uint32 DacDrvConfigure(void *drv, struct BusConfigureInfo *configure_info
|
||||||
{
|
{
|
||||||
case OPE_CFG:
|
case OPE_CFG:
|
||||||
dac_cfg->digital_data = *(uint16 *)configure_info->private_data;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -102,8 +345,8 @@ static const struct DacDevDone dev_done =
|
||||||
{
|
{
|
||||||
DacOpen,
|
DacOpen,
|
||||||
DacClose,
|
DacClose,
|
||||||
|
DacWrite,
|
||||||
NONE,
|
NONE,
|
||||||
DacRead,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int HwDacInit(void)
|
int HwDacInit(void)
|
||||||
|
|
|
@ -263,7 +263,7 @@ err_t ethernetif_init(struct netif* netif)
|
||||||
if (EOK != lwip_netdev_add(netif)) {
|
if (EOK != lwip_netdev_add(netif)) {
|
||||||
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
SYS_KDEBUG_LOG(NETDEV_DEBUG, ("[%s] LWIP add netdev failed.\n", __func__));
|
||||||
} else {
|
} else {
|
||||||
printf("[%s] Add Netdev successful\n", __func__);
|
// printf("[%s] Add Netdev successful\n", __func__);
|
||||||
}
|
}
|
||||||
return LL_OK;
|
return LL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,9 @@ static uint32 I2cDrvConfigure(void *drv, struct BusConfigureInfo *configure_info
|
||||||
|
|
||||||
static uint32 I2cMasterWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
|
static uint32 I2cMasterWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg)
|
||||||
{
|
{
|
||||||
|
if (msg->len == 0) {
|
||||||
|
return EOK;
|
||||||
|
}
|
||||||
uint32 i32Ret;
|
uint32 i32Ret;
|
||||||
|
|
||||||
I2C_Cmd(I2C_UNIT, ENABLE);
|
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) {
|
static uint32 I2cSlaveWriteData(struct I2cHardwareDevice *i2c_dev, struct I2cDataStandard *msg) {
|
||||||
|
if (msg->len == 0) {
|
||||||
|
return EOK;
|
||||||
|
}
|
||||||
uint32 i32Ret;
|
uint32 i32Ret;
|
||||||
|
|
||||||
I2C_Cmd(I2C_UNIT, ENABLE);
|
I2C_Cmd(I2C_UNIT, ENABLE);
|
||||||
|
|
|
@ -34,13 +34,6 @@ struct HwDac
|
||||||
uint16 digital_data;
|
uint16 digital_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CM_DAC_TypeDef *pUnit;
|
|
||||||
// en_dac_cvt_t enCvtType;
|
|
||||||
uint16_t u16Ch;
|
|
||||||
} stc_dac_handle_t;
|
|
||||||
|
|
||||||
|
|
||||||
int HwDacInit(void);
|
int HwDacInit(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -572,7 +572,8 @@ endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_TOOL_SHELL), y)
|
ifeq ($(CONFIG_TOOL_SHELL), y)
|
||||||
KERNELPATHS +=-I$(KERNEL_ROOT)/tool/shell/letter-shell \
|
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
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_TOOL_USING_OTA), y)
|
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_NAME "tcp"
|
||||||
#define TCPIP_THREAD_STACKSIZE 2048
|
#define TCPIP_THREAD_STACKSIZE 2048
|
||||||
#define TCPIP_MBOX_SIZE 16
|
#define TCPIP_MBOX_SIZE 16
|
||||||
#define TCPIP_THREAD_PRIO 20
|
#define TCPIP_THREAD_PRIO 30
|
||||||
|
|
||||||
/*
|
/*
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
|
@ -336,7 +336,7 @@ void lwip_config_input(struct netif* net)
|
||||||
{
|
{
|
||||||
sys_thread_t th_id = 0;
|
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) {
|
if (th_id >= 0) {
|
||||||
lw_print("%s %d successfully!\n", __func__, th_id);
|
lw_print("%s %d successfully!\n", __func__, th_id);
|
||||||
|
@ -347,6 +347,12 @@ void lwip_config_input(struct netif* net)
|
||||||
|
|
||||||
void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw)
|
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;
|
||||||
|
|
||||||
sys_sem_new(get_eth_recv_sem(), 0);
|
sys_sem_new(get_eth_recv_sem(), 0);
|
||||||
|
|
||||||
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
ip4_addr_t net_ipaddr, net_netmask, net_gw;
|
||||||
|
@ -371,7 +377,6 @@ void lwip_config_tcp(uint8_t enet_port, char* ip, char* mask, char* gw)
|
||||||
|
|
||||||
if (0 == enet_port) {
|
if (0 == enet_port) {
|
||||||
#ifdef NETIF_ENET0_INIT_FUNC
|
#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,
|
netif_add(&gnetif, &net_ipaddr, &net_netmask, &net_gw, eth_cfg, NETIF_ENET0_INIT_FUNC,
|
||||||
tcpip_input);
|
tcpip_input);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,27 +19,67 @@
|
||||||
*/
|
*/
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "sys_arch.h"
|
#include "sys_arch.h"
|
||||||
#include "lwip/udp.h"
|
|
||||||
#include <shell.h>
|
|
||||||
#include <sys.h>
|
#include <sys.h>
|
||||||
#include <xizi.h>
|
#include <xizi.h>
|
||||||
#include "lwip/sockets.h"
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lwip/sockets.h"
|
||||||
|
#include "lwip/udp.h"
|
||||||
|
|
||||||
|
#include <argparse.h>
|
||||||
|
#include <shell.h>
|
||||||
|
|
||||||
#define PBUF_SIZE 27
|
#define PBUF_SIZE 27
|
||||||
|
|
||||||
static struct udp_pcb *udpecho_raw_pcb;
|
static struct udp_pcb *udpecho_raw_pcb;
|
||||||
|
|
||||||
char udp_server_ip[] = {192, 168, 130, 2};
|
|
||||||
u16_t udp_server_port = LWIP_TARGET_PORT;
|
u16_t udp_server_port = LWIP_TARGET_PORT;
|
||||||
int32 udp_send_num = 0;
|
#define UDP_BUFFER_SIZE 50
|
||||||
int8 udp_send_task_on = 0;
|
|
||||||
uint32 udp_interval = 50;
|
|
||||||
|
|
||||||
char hello_str[] = {"hello world\r\n"};
|
char hello_str[] = {"hello world\r\n"};
|
||||||
char udp_demo_msg[] = "\nThis one is UDP package!!!\n";
|
char udp_demo_buffer[UDP_BUFFER_SIZE] = { '\0' };
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
enum LwipUdpSendParamEnum {
|
||||||
|
TARGET_IP = 0,
|
||||||
|
TARGET_PORT = 'p',
|
||||||
|
SEND_MESSAGE = 'm',
|
||||||
|
SEND_NUM = 'n',
|
||||||
|
SEND_INTERVAL = 'i',
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LwipUdpSendParam {
|
||||||
|
uint32_t num;
|
||||||
|
uint32_t interval;
|
||||||
|
uint16_t port;
|
||||||
|
uint8_t ip[4];
|
||||||
|
bool task_on;
|
||||||
|
bool given_ip;
|
||||||
|
bool given_port;
|
||||||
|
bool given_msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LwipUdpSendParam* get_udp_test_info()
|
||||||
|
{
|
||||||
|
/* init once and init when used. */
|
||||||
|
static struct LwipUdpSendParam g_udp_send_param = {
|
||||||
|
.interval = 100,
|
||||||
|
.num = 10,
|
||||||
|
.port = LWIP_TARGET_PORT,
|
||||||
|
.ip = { 127, 0, 0, 1 },
|
||||||
|
.task_on = false,
|
||||||
|
.given_ip = false,
|
||||||
|
.given_port = false,
|
||||||
|
.given_msg = false,
|
||||||
|
};
|
||||||
|
return &g_udp_send_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* const usages[] = {
|
||||||
|
"UDPSend [--options arg] [-option arg]",
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
static void LwipUDPSendTask(void *arg)
|
static void LwipUDPSendTask(void *arg)
|
||||||
{
|
{
|
||||||
|
@ -56,8 +96,8 @@ static void LwipUDPSendTask(void *arg)
|
||||||
|
|
||||||
struct sockaddr_in udp_sock;
|
struct sockaddr_in udp_sock;
|
||||||
udp_sock.sin_family = AF_INET;
|
udp_sock.sin_family = AF_INET;
|
||||||
udp_sock.sin_port = htons(udp_server_port);
|
udp_sock.sin_port = htons(get_udp_test_info()->port);
|
||||||
udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(udp_server_ip[0], udp_server_ip[1], udp_server_ip[2], udp_server_ip[3]));
|
udp_sock.sin_addr.s_addr = PP_HTONL(LWIP_MAKEU32(get_udp_test_info()->ip[0], get_udp_test_info()->ip[1], get_udp_test_info()->ip[2], get_udp_test_info()->ip[3]));
|
||||||
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
|
memset(&(udp_sock.sin_zero), 0, sizeof(udp_sock.sin_zero));
|
||||||
|
|
||||||
if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) {
|
if (connect(socket_fd, (struct sockaddr *)&udp_sock, sizeof(struct sockaddr))) {
|
||||||
|
@ -68,59 +108,81 @@ static void LwipUDPSendTask(void *arg)
|
||||||
|
|
||||||
KPrintf("UDP connect success, start to send.\n");
|
KPrintf("UDP connect success, start to send.\n");
|
||||||
KPrintf("\n\nTarget Port:%d\n\n", udp_sock.sin_port);
|
KPrintf("\n\nTarget Port:%d\n\n", udp_sock.sin_port);
|
||||||
udp_send_task_on = 1;
|
get_udp_test_info()->task_on = true;
|
||||||
|
|
||||||
while(udp_send_num > 0 || udp_send_num == -1) {
|
while (get_udp_test_info()->num > 0 || get_udp_test_info()->num == -1) {
|
||||||
sendto(socket_fd, udp_demo_msg, strlen(udp_demo_msg), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr));
|
sendto(socket_fd, udp_demo_buffer, strlen(udp_demo_buffer), 0, (struct sockaddr*)&udp_sock, sizeof(struct sockaddr));
|
||||||
KPrintf("Send UDP msg: %s \n", udp_demo_msg);
|
KPrintf("Send UDP msg: %s \n", udp_demo_buffer);
|
||||||
MdelayKTask(udp_interval);
|
MdelayKTask(get_udp_test_info()->interval);
|
||||||
udp_send_num--;
|
get_udp_test_info()->num--;
|
||||||
}
|
}
|
||||||
closesocket(socket_fd);
|
closesocket(socket_fd);
|
||||||
udp_send_task_on = 0;
|
get_udp_test_info()->task_on = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *LwipUdpSendTest(int argc, char *argv[])
|
static int LwipUdpSend(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
if(udp_send_task_on) {
|
static char usage_info[] = "Send udp NUM message to IP:PORT with time INTERVAL between each message send.";
|
||||||
udp_send_num = 0;
|
static char program_info[] = "UDP SEND TEST DEMO.";
|
||||||
printf("waitting send task exit...\n");
|
|
||||||
while(udp_send_task_on){
|
/* Wait if there are former udp task */
|
||||||
|
if (get_udp_test_info()->task_on) {
|
||||||
|
KPrintf("[%s] Waiting former udp send task to exit.\n");
|
||||||
|
}
|
||||||
|
while (get_udp_test_info()->task_on) {
|
||||||
MdelayKTask(1000);
|
MdelayKTask(1000);
|
||||||
}
|
}
|
||||||
udp_send_num = 1;
|
|
||||||
|
get_udp_test_info()->given_ip = false;
|
||||||
|
get_udp_test_info()->given_port = false;
|
||||||
|
get_udp_test_info()->given_msg = false;
|
||||||
|
|
||||||
|
/* Parse options */
|
||||||
|
char* msg_ptr = NULL;
|
||||||
|
char* ip_ptr = NULL;
|
||||||
|
bool is_help = false;
|
||||||
|
struct argparse_option options[] = {
|
||||||
|
OPT_HELP(&is_help),
|
||||||
|
OPT_STRING(SEND_MESSAGE, "message", &msg_ptr, "MESSAGE to send", NULL, 0, 0),
|
||||||
|
OPT_STRING(TARGET_IP, "ip", &ip_ptr, "target IP to send upd messages", NULL, 0, 0),
|
||||||
|
OPT_INTEGER(TARGET_PORT, "port", &get_udp_test_info()->port, "target PORT to send udp messages", NULL, 0, 0),
|
||||||
|
OPT_INTEGER(SEND_NUM, "num", &get_udp_test_info()->num, "send NUM udp messages", NULL, 0, 0),
|
||||||
|
OPT_INTEGER(SEND_INTERVAL, "interval", &get_udp_test_info()->interval, "time INTERVAL between messages", NULL, 0, 0),
|
||||||
|
OPT_END(),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct argparse argparse;
|
||||||
|
argparse_init(&argparse, options, usages, 0);
|
||||||
|
argparse_describe(&argparse, usage_info, program_info);
|
||||||
|
argc = argparse_parse(&argparse, argc, (const char**)argv);
|
||||||
|
if (argc < 0) {
|
||||||
|
KPrintf("Error options.\n");
|
||||||
|
return -ERROR;
|
||||||
|
}
|
||||||
|
if (is_help) {
|
||||||
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t enet_port = 0; ///< test enet port 0
|
// translate string to array
|
||||||
memset(udp_demo_msg, 0, sizeof(udp_demo_msg));
|
sscanf(ip_ptr, "%d.%d.%d.%d", &get_udp_test_info()->ip[0], &get_udp_test_info()->ip[1], &get_udp_test_info()->ip[2], &get_udp_test_info()->ip[3]);
|
||||||
|
int msg_len = strlen(msg_ptr);
|
||||||
|
strncpy(udp_demo_buffer, msg_ptr, msg_len < UDP_BUFFER_SIZE ? msg_len : UDP_BUFFER_SIZE);
|
||||||
|
|
||||||
if(argc == 1) {
|
/* start task */
|
||||||
KPrintf("lw: [%s] gw %d.%d.%d.%d:%d\n", __func__, udp_server_ip[0], udp_server_ip[1], udp_server_ip[2], udp_server_ip[3], udp_server_port);
|
KPrintf("[%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__,
|
||||||
strncpy(udp_demo_msg, hello_str, strlen(hello_str));
|
get_udp_test_info()->ip[0], get_udp_test_info()->ip[1], get_udp_test_info()->ip[2], get_udp_test_info()->ip[3],
|
||||||
udp_send_num = 10;
|
get_udp_test_info()->port,
|
||||||
udp_interval = 100;
|
get_udp_test_info()->num,
|
||||||
} else {
|
get_udp_test_info()->interval);
|
||||||
strncpy(udp_demo_msg, argv[1], strlen(argv[1]));
|
|
||||||
strncat(udp_demo_msg, "\r\n", 3);
|
|
||||||
if(argc >= 3) {
|
|
||||||
sscanf(argv[2], "%d.%d.%d.%d:%d", &udp_server_ip[0], &udp_server_ip[1], &udp_server_ip[2], &udp_server_ip[3], &udp_server_port);
|
|
||||||
}
|
|
||||||
if(argc > 3) {
|
|
||||||
sscanf(argv[3], "%d", &udp_send_num);
|
|
||||||
sscanf(argv[4], "%d", &udp_interval);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
KPrintf("lw: [%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__, udp_server_ip[0], udp_server_ip[1], udp_server_ip[2], udp_server_ip[3], udp_server_port, udp_send_num, udp_interval);
|
lwip_config_net(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
||||||
|
|
||||||
//init lwip and net dirver
|
|
||||||
lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
|
|
||||||
sys_thread_new("udp send", LwipUDPSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
sys_thread_new("udp send", LwipUDPSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
|
||||||
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(5),
|
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN) | SHELL_CMD_PARAM_NUM(16),
|
||||||
UDPSend, LwipUdpSendTest, UDPSend msg [ip:port [num [interval]]]);
|
UDPSend, LwipUdpSend, UDPSend Demo);
|
||||||
|
|
||||||
void LwipUdpRecvTest(void)
|
void LwipUdpRecvTest(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
SRC_DIR := letter-shell
|
SRC_DIR := letter-shell
|
||||||
|
SRC_FILES += argparse.c
|
||||||
|
|
||||||
include $(KERNEL_ROOT)/compiler.mk
|
include $(KERNEL_ROOT)/compiler.mk
|
||||||
|
|
|
@ -0,0 +1,389 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a MIT-style license that can be found
|
||||||
|
* in the LICENSE file.
|
||||||
|
*/
|
||||||
|
#include "argparse.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define OPT_UNSET 1
|
||||||
|
#define OPT_LONG (1 << 1)
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
prefix_skip(const char* str, const char* prefix)
|
||||||
|
{
|
||||||
|
size_t len = strlen(prefix);
|
||||||
|
return strncmp(str, prefix, len) ? NULL : str + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
prefix_cmp(const char* str, const char* prefix)
|
||||||
|
{
|
||||||
|
for (;; str++, prefix++)
|
||||||
|
if (!*prefix) {
|
||||||
|
return 0;
|
||||||
|
} else if (*str != *prefix) {
|
||||||
|
return (unsigned char)*prefix - (unsigned char)*str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
argparse_error(struct argparse* self, const struct argparse_option* opt,
|
||||||
|
const char* reason, int flags)
|
||||||
|
{
|
||||||
|
(void)self;
|
||||||
|
if (flags & OPT_LONG) {
|
||||||
|
fprintf(stderr, "error: option `--%s` %s\n", opt->long_name, reason);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "error: option `-%c` %s\n", opt->short_name, reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <xizi.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
argparse_getvalue(struct argparse* self, const struct argparse_option* opt,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
const char* s = NULL;
|
||||||
|
if (!opt->value)
|
||||||
|
goto skipped;
|
||||||
|
switch (opt->type) {
|
||||||
|
case ARGPARSE_OPT_BOOLEAN:
|
||||||
|
if (flags & OPT_UNSET) {
|
||||||
|
*(int*)opt->value = *(int*)opt->value - 1;
|
||||||
|
} else {
|
||||||
|
*(int*)opt->value = *(int*)opt->value + 1;
|
||||||
|
}
|
||||||
|
if (*(int*)opt->value < 0) {
|
||||||
|
*(int*)opt->value = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARGPARSE_OPT_BIT:
|
||||||
|
if (flags & OPT_UNSET) {
|
||||||
|
*(int*)opt->value &= ~opt->data;
|
||||||
|
} else {
|
||||||
|
*(int*)opt->value |= opt->data;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARGPARSE_OPT_STRING:
|
||||||
|
if (self->optvalue) {
|
||||||
|
*(const char**)opt->value = self->optvalue;
|
||||||
|
self->optvalue = NULL;
|
||||||
|
} else if (self->argc > 1) {
|
||||||
|
self->argc--;
|
||||||
|
*(const char**)opt->value = *++self->argv;
|
||||||
|
} else {
|
||||||
|
argparse_error(self, opt, "requires a value", flags);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARGPARSE_OPT_INTEGER:
|
||||||
|
errno = 0;
|
||||||
|
if (self->optvalue) {
|
||||||
|
*(int*)opt->value = strtol(self->optvalue, (char**)&s, 0);
|
||||||
|
self->optvalue = NULL;
|
||||||
|
} else if (self->argc > 1) {
|
||||||
|
self->argc--;
|
||||||
|
*(int*)opt->value = strtol(*++self->argv, (char**)&s, 0);
|
||||||
|
} else {
|
||||||
|
argparse_error(self, opt, "requires a value", flags);
|
||||||
|
}
|
||||||
|
if (errno == ERANGE)
|
||||||
|
argparse_error(self, opt, "numerical result out of range", flags);
|
||||||
|
if (s[0] != '\0') // no digits or contains invalid characters
|
||||||
|
argparse_error(self, opt, "expects an integer value", flags);
|
||||||
|
break;
|
||||||
|
case ARGPARSE_OPT_FLOAT:
|
||||||
|
errno = 0;
|
||||||
|
if (self->optvalue) {
|
||||||
|
*(float*)opt->value = strtof(self->optvalue, (char**)&s);
|
||||||
|
self->optvalue = NULL;
|
||||||
|
} else if (self->argc > 1) {
|
||||||
|
self->argc--;
|
||||||
|
*(float*)opt->value = strtof(*++self->argv, (char**)&s);
|
||||||
|
} else {
|
||||||
|
argparse_error(self, opt, "requires a value", flags);
|
||||||
|
}
|
||||||
|
if (errno == ERANGE)
|
||||||
|
argparse_error(self, opt, "numerical result out of range", flags);
|
||||||
|
if (s[0] != '\0') // no digits or contains invalid characters
|
||||||
|
argparse_error(self, opt, "expects a numerical value", flags);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
skipped:
|
||||||
|
if (opt->callback) {
|
||||||
|
return opt->callback(self, opt);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
argparse_options_check(const struct argparse_option* options)
|
||||||
|
{
|
||||||
|
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||||
|
switch (options->type) {
|
||||||
|
case ARGPARSE_OPT_END:
|
||||||
|
case ARGPARSE_OPT_BOOLEAN:
|
||||||
|
case ARGPARSE_OPT_BIT:
|
||||||
|
case ARGPARSE_OPT_INTEGER:
|
||||||
|
case ARGPARSE_OPT_FLOAT:
|
||||||
|
case ARGPARSE_OPT_STRING:
|
||||||
|
case ARGPARSE_OPT_GROUP:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "wrong option type: %d", options->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
argparse_short_opt(struct argparse* self, const struct argparse_option* options)
|
||||||
|
{
|
||||||
|
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||||
|
if (options->short_name == *self->optvalue) {
|
||||||
|
self->optvalue = self->optvalue[1] ? self->optvalue + 1 : NULL;
|
||||||
|
return argparse_getvalue(self, options, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
argparse_long_opt(struct argparse* self, const struct argparse_option* options)
|
||||||
|
{
|
||||||
|
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||||
|
const char* rest;
|
||||||
|
int opt_flags = 0;
|
||||||
|
if (!options->long_name)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rest = prefix_skip(self->argv[0] + 2, options->long_name);
|
||||||
|
if (!rest) {
|
||||||
|
// negation disabled?
|
||||||
|
if (options->flags & OPT_NONEG) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// only OPT_BOOLEAN/OPT_BIT supports negation
|
||||||
|
if (options->type != ARGPARSE_OPT_BOOLEAN && options->type != ARGPARSE_OPT_BIT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefix_cmp(self->argv[0] + 2, "no-")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rest = prefix_skip(self->argv[0] + 2 + 3, options->long_name);
|
||||||
|
if (!rest)
|
||||||
|
continue;
|
||||||
|
opt_flags |= OPT_UNSET;
|
||||||
|
}
|
||||||
|
if (*rest) {
|
||||||
|
if (*rest != '=')
|
||||||
|
continue;
|
||||||
|
self->optvalue = rest + 1;
|
||||||
|
}
|
||||||
|
return argparse_getvalue(self, options, opt_flags | OPT_LONG);
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argparse_init(struct argparse* self, struct argparse_option* options,
|
||||||
|
const char* const* usages, int flags)
|
||||||
|
{
|
||||||
|
memset(self, 0, sizeof(*self));
|
||||||
|
self->options = options;
|
||||||
|
self->usages = usages;
|
||||||
|
self->flags = flags;
|
||||||
|
self->description = NULL;
|
||||||
|
self->epilog = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void argparse_describe(struct argparse* self, const char* description,
|
||||||
|
const char* epilog)
|
||||||
|
{
|
||||||
|
self->description = description;
|
||||||
|
self->epilog = epilog;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argparse_parse(struct argparse* self, int argc, const char** argv)
|
||||||
|
{
|
||||||
|
self->argc = argc - 1;
|
||||||
|
self->argv = argv + 1;
|
||||||
|
self->out = argv;
|
||||||
|
|
||||||
|
argparse_options_check(self->options);
|
||||||
|
|
||||||
|
for (; self->argc; self->argc--, self->argv++) {
|
||||||
|
const char* arg = self->argv[0];
|
||||||
|
if (arg[0] != '-' || !arg[1]) {
|
||||||
|
if (self->flags & ARGPARSE_STOP_AT_NON_OPTION) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
// if it's not option or is a single char '-', copy verbatim
|
||||||
|
self->out[self->cpidx++] = self->argv[0];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// short option
|
||||||
|
if (arg[1] != '-') {
|
||||||
|
self->optvalue = arg + 1;
|
||||||
|
switch (argparse_short_opt(self, self->options)) {
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
goto unknown;
|
||||||
|
}
|
||||||
|
while (self->optvalue) {
|
||||||
|
switch (argparse_short_opt(self, self->options)) {
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
goto unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// if '--' presents
|
||||||
|
if (!arg[2]) {
|
||||||
|
self->argc--;
|
||||||
|
self->argv++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// long option
|
||||||
|
switch (argparse_long_opt(self, self->options)) {
|
||||||
|
case -1:
|
||||||
|
break;
|
||||||
|
case -2:
|
||||||
|
goto unknown;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unknown:
|
||||||
|
fprintf(stderr, "error: unknown option `%s`\n", self->argv[0]);
|
||||||
|
argparse_usage(self);
|
||||||
|
if (!(self->flags & ARGPARSE_IGNORE_UNKNOWN_ARGS)) {
|
||||||
|
return ARGPARSE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
memmove(self->out + self->cpidx, self->argv,
|
||||||
|
self->argc * sizeof(*self->out));
|
||||||
|
self->out[self->cpidx + self->argc] = NULL;
|
||||||
|
|
||||||
|
return self->cpidx + self->argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void argparse_usage(struct argparse* self)
|
||||||
|
{
|
||||||
|
if (self->usages) {
|
||||||
|
fprintf(stdout, "Usage: %s\n", *self->usages++);
|
||||||
|
while (*self->usages && **self->usages)
|
||||||
|
fprintf(stdout, " or: %s\n", *self->usages++);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "Usage:\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// print description
|
||||||
|
if (self->description)
|
||||||
|
fprintf(stdout, "%s\n", self->description);
|
||||||
|
|
||||||
|
fputc('\n', stdout);
|
||||||
|
|
||||||
|
const struct argparse_option* options;
|
||||||
|
|
||||||
|
// figure out best width
|
||||||
|
size_t usage_opts_width = 0;
|
||||||
|
size_t len;
|
||||||
|
options = self->options;
|
||||||
|
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||||
|
len = 0;
|
||||||
|
if ((options)->short_name) {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
if ((options)->short_name && (options)->long_name) {
|
||||||
|
len += 2; // separator ", "
|
||||||
|
}
|
||||||
|
if ((options)->long_name) {
|
||||||
|
len += strlen((options)->long_name) + 2;
|
||||||
|
}
|
||||||
|
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||||
|
len += strlen("=<int>");
|
||||||
|
}
|
||||||
|
if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||||
|
len += strlen("=<flt>");
|
||||||
|
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||||
|
len += strlen("=<str>");
|
||||||
|
}
|
||||||
|
len = (len + 3) - ((len + 3) & 3);
|
||||||
|
if (usage_opts_width < len) {
|
||||||
|
usage_opts_width = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usage_opts_width += 4; // 4 spaces prefix
|
||||||
|
|
||||||
|
options = self->options;
|
||||||
|
for (; options->type != ARGPARSE_OPT_END; options++) {
|
||||||
|
size_t pos = 0;
|
||||||
|
size_t pad = 0;
|
||||||
|
if (options->type == ARGPARSE_OPT_GROUP) {
|
||||||
|
fputc('\n', stdout);
|
||||||
|
fprintf(stdout, "%s", options->help);
|
||||||
|
fputc('\n', stdout);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pos = fprintf(stdout, " ");
|
||||||
|
if (options->short_name) {
|
||||||
|
pos += fprintf(stdout, "-%c", options->short_name);
|
||||||
|
}
|
||||||
|
if (options->long_name && options->short_name) {
|
||||||
|
pos += fprintf(stdout, ", ");
|
||||||
|
}
|
||||||
|
if (options->long_name) {
|
||||||
|
pos += fprintf(stdout, "--%s", options->long_name);
|
||||||
|
}
|
||||||
|
if (options->type == ARGPARSE_OPT_INTEGER) {
|
||||||
|
pos += fprintf(stdout, "=<int>");
|
||||||
|
} else if (options->type == ARGPARSE_OPT_FLOAT) {
|
||||||
|
pos += fprintf(stdout, "=<flt>");
|
||||||
|
} else if (options->type == ARGPARSE_OPT_STRING) {
|
||||||
|
pos += fprintf(stdout, "=<str>");
|
||||||
|
}
|
||||||
|
if (pos <= usage_opts_width) {
|
||||||
|
pad = usage_opts_width - pos;
|
||||||
|
} else {
|
||||||
|
fputc('\n', stdout);
|
||||||
|
pad = usage_opts_width;
|
||||||
|
}
|
||||||
|
fprintf(stdout, "%*s%s\n", (int)pad + 2, "", options->help);
|
||||||
|
}
|
||||||
|
|
||||||
|
// print epilog
|
||||||
|
if (self->epilog)
|
||||||
|
fprintf(stdout, "%s\n", self->epilog);
|
||||||
|
}
|
||||||
|
|
||||||
|
int argparse_help_cb_no_exit(struct argparse* self,
|
||||||
|
const struct argparse_option* option)
|
||||||
|
{
|
||||||
|
(void)option;
|
||||||
|
argparse_usage(self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int argparse_help_cb(struct argparse* self, const struct argparse_option* option)
|
||||||
|
{
|
||||||
|
argparse_help_cb_no_exit(self, option);
|
||||||
|
*(bool*)option->value = true;
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2012-2015 Yecheng Fu <cofyc.jackson at gmail dot com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a MIT-style license that can be found
|
||||||
|
* in the LICENSE file.
|
||||||
|
*/
|
||||||
|
#ifndef ARGPARSE_H
|
||||||
|
#define ARGPARSE_H
|
||||||
|
|
||||||
|
/* For c++ compatibility */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define ARGPARSE_HELP_DONE -1
|
||||||
|
#define ARGPARSE_ERROR -2
|
||||||
|
|
||||||
|
struct argparse;
|
||||||
|
struct argparse_option;
|
||||||
|
|
||||||
|
typedef int argparse_callback(struct argparse* self,
|
||||||
|
const struct argparse_option* option);
|
||||||
|
|
||||||
|
enum argparse_flag {
|
||||||
|
ARGPARSE_STOP_AT_NON_OPTION = 1 << 0,
|
||||||
|
ARGPARSE_IGNORE_UNKNOWN_ARGS = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum argparse_option_type {
|
||||||
|
/* special */
|
||||||
|
ARGPARSE_OPT_END,
|
||||||
|
ARGPARSE_OPT_GROUP,
|
||||||
|
/* options with no arguments */
|
||||||
|
ARGPARSE_OPT_BOOLEAN,
|
||||||
|
ARGPARSE_OPT_BIT,
|
||||||
|
/* options with arguments (optional or required) */
|
||||||
|
ARGPARSE_OPT_INTEGER,
|
||||||
|
ARGPARSE_OPT_FLOAT,
|
||||||
|
ARGPARSE_OPT_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum argparse_option_flags {
|
||||||
|
OPT_NONEG = 1, /* disable negation */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* argparse option
|
||||||
|
*
|
||||||
|
* `type`:
|
||||||
|
* holds the type of the option, you must have an ARGPARSE_OPT_END last in your
|
||||||
|
* array.
|
||||||
|
*
|
||||||
|
* `short_name`:
|
||||||
|
* the character to use as a short option name, '\0' if none.
|
||||||
|
*
|
||||||
|
* `long_name`:
|
||||||
|
* the long option name, without the leading dash, NULL if none.
|
||||||
|
*
|
||||||
|
* `value`:
|
||||||
|
* stores pointer to the value to be filled.
|
||||||
|
*
|
||||||
|
* `help`:
|
||||||
|
* the short help message associated to what the option does.
|
||||||
|
* Must never be NULL (except for ARGPARSE_OPT_END).
|
||||||
|
*
|
||||||
|
* `callback`:
|
||||||
|
* function is called when corresponding argument is parsed.
|
||||||
|
*
|
||||||
|
* `data`:
|
||||||
|
* associated data. Callbacks can use it like they want.
|
||||||
|
*
|
||||||
|
* `flags`:
|
||||||
|
* option flags.
|
||||||
|
*/
|
||||||
|
struct argparse_option {
|
||||||
|
enum argparse_option_type type;
|
||||||
|
const char short_name;
|
||||||
|
const char* long_name;
|
||||||
|
void* value;
|
||||||
|
const char* help;
|
||||||
|
argparse_callback* callback;
|
||||||
|
intptr_t data;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* argpparse
|
||||||
|
*/
|
||||||
|
struct argparse {
|
||||||
|
// user supplied
|
||||||
|
const struct argparse_option* options;
|
||||||
|
const char* const* usages;
|
||||||
|
int flags;
|
||||||
|
const char* description; // a description after usage
|
||||||
|
const char* epilog; // a description at the end
|
||||||
|
// internal context
|
||||||
|
int argc;
|
||||||
|
const char** argv;
|
||||||
|
const char** out;
|
||||||
|
int cpidx;
|
||||||
|
const char* optvalue; // current option value
|
||||||
|
};
|
||||||
|
|
||||||
|
// built-in callbacks
|
||||||
|
int argparse_help_cb(struct argparse* self,
|
||||||
|
const struct argparse_option* option);
|
||||||
|
int argparse_help_cb_no_exit(struct argparse* self,
|
||||||
|
const struct argparse_option* option);
|
||||||
|
|
||||||
|
// built-in option macros
|
||||||
|
#define OPT_END() \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_END, 0, NULL, NULL, 0, NULL, 0, 0 \
|
||||||
|
}
|
||||||
|
#define OPT_BOOLEAN(...) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_BOOLEAN, __VA_ARGS__ \
|
||||||
|
}
|
||||||
|
#define OPT_BIT(...) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_BIT, __VA_ARGS__ \
|
||||||
|
}
|
||||||
|
#define OPT_INTEGER(...) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_INTEGER, __VA_ARGS__ \
|
||||||
|
}
|
||||||
|
#define OPT_FLOAT(...) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_FLOAT, __VA_ARGS__ \
|
||||||
|
}
|
||||||
|
#define OPT_STRING(...) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_STRING, __VA_ARGS__ \
|
||||||
|
}
|
||||||
|
#define OPT_GROUP(h) \
|
||||||
|
{ \
|
||||||
|
ARGPARSE_OPT_GROUP, 0, NULL, NULL, h, NULL, 0, 0 \
|
||||||
|
}
|
||||||
|
#define OPT_HELP(flag) OPT_BOOLEAN('h', "help", flag, \
|
||||||
|
"show this help message and exit", \
|
||||||
|
argparse_help_cb, 0, OPT_NONEG)
|
||||||
|
|
||||||
|
int argparse_init(struct argparse* self, struct argparse_option* options,
|
||||||
|
const char* const* usages, int flags);
|
||||||
|
void argparse_describe(struct argparse* self, const char* description,
|
||||||
|
const char* epilog);
|
||||||
|
int argparse_parse(struct argparse* self, int argc, const char** argv);
|
||||||
|
void argparse_usage(struct argparse* self);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue