forked from xuos/xiuos
				
			update prepare_for_master latest commit(90b7740ca0) to 2023_open_source_contest from Liu_Weichao
it is OK
This commit is contained in:
		
						commit
						7d3d4651d3
					
				| 
						 | 
					@ -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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PrivRead(adc_fd, &adc_sample, 2);
 | 
					    for (int i = 0; i < 10; i ++) {
 | 
				
			||||||
 | 
					        PrivRead(adc_fd, &adc_sample, 2);
 | 
				
			||||||
    adc_value = (float)adc_sample * (3.3 / 4096);
 | 
					        printf("adc sample %u mv\n", adc_sample);
 | 
				
			||||||
 | 
					        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,11 +28,11 @@
 | 
				
			||||||
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;
 | 
				
			||||||
    PrivWrite(pin_fd,&pin_led,NULL_PARAMETER);
 | 
					    PrivWrite(pin_fd, &pin_led, NULL_PARAMETER);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void TestHwTimer(void)
 | 
					void TestHwTimer(void)
 | 
				
			||||||
| 
						 | 
					@ -40,22 +40,22 @@ void TestHwTimer(void)
 | 
				
			||||||
    x_ticks_t period = 100000;
 | 
					    x_ticks_t period = 100000;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    pin_fd = PrivOpen(HWTIMER_PIN_DEV_DRIVER, O_RDWR);
 | 
					    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);
 | 
					        printf("open pin fd error:%d\n",pin_fd);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int timer_fd = PrivOpen(HWTIMER_TIMER_DEV_DRIVER, O_RDWR);
 | 
					    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);
 | 
					        printf("open timer fd error:%d\n",timer_fd);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //config led pin in board
 | 
					    //config led pin in board
 | 
				
			||||||
     struct PinParam parameter;
 | 
					    struct PinParam parameter;
 | 
				
			||||||
     parameter.cmd = GPIO_CONFIG_MODE;
 | 
					    parameter.cmd = GPIO_CONFIG_MODE;
 | 
				
			||||||
     parameter.pin = BSP_LED_PIN;
 | 
					    parameter.pin = BSP_LED_PIN;
 | 
				
			||||||
     parameter.mode = GPIO_CFG_OUTPUT;
 | 
					    parameter.mode = GPIO_CFG_OUTPUT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct PrivIoctlCfg ioctl_cfg;
 | 
					    struct PrivIoctlCfg ioctl_cfg;
 | 
				
			||||||
    ioctl_cfg.ioctl_driver_type = PIN_TYPE;
 | 
					    ioctl_cfg.ioctl_driver_type = PIN_TYPE;
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					@ -82,13 +82,10 @@ void TestHwTimer(void)
 | 
				
			||||||
        return;
 | 
					        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(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)
 | 
					
 | 
				
			||||||
    {
 | 
					static const int nr_transmit = 15;
 | 
				
			||||||
        PrivTaskDelay(1000);
 | 
					
 | 
				
			||||||
        PrivWrite(iic_fd, "Hello World!\n", sizeof("Hello World!\n"));
 | 
					void TestMasterI2c(void)
 | 
				
			||||||
        printf("msg send:%s\n", "Hello World!\n");
 | 
					{
 | 
				
			||||||
        PrivTaskDelay(1000);
 | 
					    char recv_buff[13] = { 0 };
 | 
				
			||||||
        memset(tmp_buff, 0, sizeof(tmp_buff));
 | 
					
 | 
				
			||||||
        PrivRead(iic_fd, tmp_buff, sizeof(tmp_buff));
 | 
					    int iic_fd = OpenIic();
 | 
				
			||||||
        printf("msg recv:%s\n", tmp_buff);
 | 
					    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);
 | 
					    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
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -22,26 +22,94 @@
 | 
				
			||||||
#include <transform.h>
 | 
					#include <transform.h>
 | 
				
			||||||
#ifdef ADD_XIZI_FEATURES
 | 
					#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)
 | 
					void Test485(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
 | 
					    int read_data_length = 0;
 | 
				
			||||||
    if (pin_fd < 0)
 | 
					    pin_fd = PrivOpen(RS485_PIN_DEV_DRIVER, O_RDWR);
 | 
				
			||||||
    {
 | 
					    if (pin_fd < 0) {
 | 
				
			||||||
        printf("open pin fd error:%d\n", pin_fd);
 | 
					        printf("open pin fd error:%d\n", pin_fd);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
 | 
					    uart_fd = PrivOpen(RS485_UART_DEV_DRIVER, O_RDWR);
 | 
				
			||||||
    if (uart_fd < 0)
 | 
					    if (uart_fd < 0) {
 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        printf("open pin fd error:%d\n", uart_fd);
 | 
					        printf("open pin fd error:%d\n", uart_fd);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    printf("uart and pin fopen success\n");
 | 
					    printf("uart and pin fopen success\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //config led pin in board
 | 
					    //config dir pin in board
 | 
				
			||||||
    struct PinParam pin_parameter;
 | 
					    struct PinParam pin_parameter;
 | 
				
			||||||
    memset(&pin_parameter, 0, sizeof(struct PinParam));
 | 
					    memset(&pin_parameter, 0, sizeof(struct PinParam));
 | 
				
			||||||
    pin_parameter.cmd = GPIO_CONFIG_MODE;
 | 
					    pin_parameter.cmd = GPIO_CONFIG_MODE;
 | 
				
			||||||
| 
						 | 
					@ -68,36 +136,34 @@ void Test485(void)
 | 
				
			||||||
    uart_cfg.serial_bit_order = BIT_ORDER_LSB;
 | 
					    uart_cfg.serial_bit_order = BIT_ORDER_LSB;
 | 
				
			||||||
    uart_cfg.serial_invert_mode = NRZ_NORMAL;
 | 
					    uart_cfg.serial_invert_mode = NRZ_NORMAL;
 | 
				
			||||||
    uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
 | 
					    uart_cfg.serial_buffer_size = SERIAL_RB_BUFSZ;
 | 
				
			||||||
    uart_cfg.serial_timeout = 1000;
 | 
					    uart_cfg.serial_timeout = -1;
 | 
				
			||||||
    uart_cfg.is_ext_uart = 0;
 | 
					    uart_cfg.is_ext_uart = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
 | 
					    ioctl_cfg.ioctl_driver_type = SERIAL_TYPE;
 | 
				
			||||||
    ioctl_cfg.args = (void *)&uart_cfg;
 | 
					    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);
 | 
					        printf("ioctl uart fd error %d\n", uart_fd);
 | 
				
			||||||
        PrivClose(uart_fd);
 | 
					        PrivClose(uart_fd);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct PinStat pin_dir;
 | 
					    Rs485Write(write_485_data, sizeof(write_485_data));
 | 
				
			||||||
    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);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pin_dir.val = GPIO_LOW;
 | 
					    while(1) {
 | 
				
			||||||
        PrivWrite(pin_fd,&pin_dir,0);
 | 
					        printf("ready to read data\n");
 | 
				
			||||||
        char recv_buff[100];
 | 
					
 | 
				
			||||||
        memset(recv_buff,0,sizeof(recv_buff));
 | 
					        read_data_length = Rs485Read(read_485_data, sizeof(read_485_data));
 | 
				
			||||||
        PrivRead(uart_fd,recv_buff,20);
 | 
					        printf("%s read data length %d\n", __func__, read_data_length);
 | 
				
			||||||
        printf("%s",recv_buff);
 | 
					        for (int i = 0; i < read_data_length; i ++) {
 | 
				
			||||||
        PrivTaskDelay(100);
 | 
					            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(pin_fd);
 | 
				
			||||||
    PrivClose(uart_fd);
 | 
					    PrivClose(uart_fd);
 | 
				
			||||||
    return;
 | 
					    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
 | 
				
			||||||
| 
						 | 
					@ -180,7 +180,7 @@ int SerialRead(uint8_t *read_data, int length)
 | 
				
			||||||
    int data_recv_size = 0;
 | 
					    int data_recv_size = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (data_size < length) {
 | 
					    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;
 | 
					        data_size += data_recv_size;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					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()
 | 
					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,8 +91,8 @@ git clone https://gitlink.org.cn/xuos/xiuos.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
使用VScode打开代码,具体操作步骤为:在源码文件夹下打开系统终端,输入`code .`即可打开VScode开发环境,如下图所示:
 | 
					使用VScode打开代码,具体操作步骤为:在源码文件夹下打开系统终端,输入`code .`即可打开VScode开发环境,如下图所示:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div align= "center"> 
 | 
					<div align= "center">
 | 
				
			||||||
<img src = img/vscode.jpg  width =1000>
 | 
					<img src="img/vscode.jpg"  width =1000>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,14 +145,14 @@ make BOARD=cortex-m4-emulator menuconfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2.在menuconfig界面配置需要关闭和开启的功能,按回车键进入下级菜单,按Y键选中需要开启的功能,按N键选中需要关闭的功能,配置结束后保存并退出(本例旨在演示简单的输出例程,所以没有需要配置的选项,双击快捷键ESC退出配置)
 | 
					2.在menuconfig界面配置需要关闭和开启的功能,按回车键进入下级菜单,按Y键选中需要开启的功能,按N键选中需要关闭的功能,配置结束后保存并退出(本例旨在演示简单的输出例程,所以没有需要配置的选项,双击快捷键ESC退出配置)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div align= "center"> 
 | 
					<div align= "center">
 | 
				
			||||||
<img src = img/menuconfig.png  width =1000>
 | 
					<img src="img/menuconfig.png"  width =1000>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
退出时选择`yes`保存上面所配置的内容,如下图所示:
 | 
					退出时选择`yes`保存上面所配置的内容,如下图所示:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div align= "center"> 
 | 
					<div align= "center">
 | 
				
			||||||
<img src = img/menuconfig1.png  width =1000>
 | 
					<img src="img/menuconfig1.png"  width =1000>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
3.继续执行以下命令,进行编译
 | 
					3.继续执行以下命令,进行编译
 | 
				
			||||||
| 
						 | 
					@ -183,8 +183,8 @@ qemu-system-arm -machine netduinoplus2  -nographic -kernel build/XiZi-cortex-m4-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QEMU运行起来后将会在终端上看到信息打印输出
 | 
					QEMU运行起来后将会在终端上看到信息打印输出
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div align= "center"> 
 | 
					<div align= "center">
 | 
				
			||||||
<img src = img/terminal.png  width =1000>
 | 
					<img src="img/terminal.png"  width =1000>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 4.3 调试
 | 
					### 4.3 调试
 | 
				
			||||||
| 
						 | 
					@ -204,5 +204,5 @@ qemu-system-arm -machine netduinoplus2  -nographic -kernel build/XiZi-cortex-m4-
 | 
				
			||||||
然后要重新开启另一个linux系统终端一个终端,执行`riscv-none-embed-gdb`命令
 | 
					然后要重新开启另一个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,74 +1,13 @@
 | 
				
			||||||
menuconfig BSP_USING_ADC1
 | 
					if BSP_USING_ADC
 | 
				
			||||||
    bool "Enable ADC1"
 | 
					    config ADC1_BUS_NAME
 | 
				
			||||||
    default y
 | 
					        string "adc 1 bus name"
 | 
				
			||||||
    if BSP_USING_ADC1
 | 
					        default "adc1"
 | 
				
			||||||
        config ADC1_BUS_NAME
 | 
					 | 
				
			||||||
            string "adc 1 bus name"
 | 
					 | 
				
			||||||
            default "adc1"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        config ADC1_DRIVER_NAME
 | 
					    config ADC1_DRIVER_NAME
 | 
				
			||||||
            string "adc 1 driver name"
 | 
					        string "adc 1 driver name"
 | 
				
			||||||
            default "adc1_drv"
 | 
					        default "adc1_drv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        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"
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
        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
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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;
 | 
					#if (ADC_CLK_SEL == ADC_CLK_SYS_CLK)
 | 
				
			||||||
	int i;
 | 
					    /*
 | 
				
			||||||
 | 
					     * 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 ++) {
 | 
					#elif (ADC_CLK_SEL == ADC_CLK_PLLH)
 | 
				
			||||||
		temp_val += ADC_GetValue(ADCx, channel) & 0x0FFF;
 | 
					    /*
 | 
				
			||||||
        KPrintf("GetAdcAverageValue val %u\n", ADC_GetValue(ADCx, channel));
 | 
					     * 1. Configures PLLH and the divider of PLLHx(x=Q, R).
 | 
				
			||||||
		AdcUdelay(5000);
 | 
					     *    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.
 | 
				
			||||||
	return temp_val / times;
 | 
					     *    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)
 | 
					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();
 | 
				
			||||||
 | 
					    read_param->read_length = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct HwAdc *adc_cfg = (struct HwAdc *)adc_dev->haldev.private_data;
 | 
					   return EOK;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    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;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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
 | 
					#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)
 | 
					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)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,7 +281,7 @@ struct pbuf* low_level_input(struct netif* netif)
 | 
				
			||||||
extern void LwipSetIPTest(int argc, char* argv[]);
 | 
					extern void LwipSetIPTest(int argc, char* argv[]);
 | 
				
			||||||
int HwEthInit(void)
 | 
					int HwEthInit(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    //   lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
					    // lwip_config_tcp(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
				
			||||||
    LwipSetIPTest(1, NULL);
 | 
					    LwipSetIPTest(1, NULL);
 | 
				
			||||||
    return EOK;
 | 
					    return EOK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					@ -222,7 +228,7 @@ static uint32 I2cSlaveReadData(struct I2cHardwareDevice *i2c_dev, struct I2cData
 | 
				
			||||||
    if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) {
 | 
					    if (RESET == I2C_GetStatus(I2C_UNIT, I2C_FLAG_TRA)) {
 | 
				
			||||||
        /* Slave receive data*/
 | 
					        /* Slave receive data*/
 | 
				
			||||||
        i32Ret = I2C_ReceiveData(I2C_UNIT, msg->buf, msg->len, I2C_TIMEOUT);
 | 
					        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)) {
 | 
					        if ((LL_OK == i32Ret) || (LL_ERR_TIMEOUT == i32Ret)) {
 | 
				
			||||||
            /* Wait stop condition */
 | 
					            /* Wait stop condition */
 | 
				
			||||||
| 
						 | 
					@ -336,7 +342,7 @@ int HwI2cInit(void)
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define I2C_TEST
 | 
					// #define I2C_TEST
 | 
				
			||||||
#ifdef I2C_TEST
 | 
					#ifdef I2C_TEST
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USER_KEY_PORT                  (GPIO_PORT_I)
 | 
					#define USER_KEY_PORT                  (GPIO_PORT_I)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,21 @@ menuconfig BSP_USING_UART3
 | 
				
			||||||
            default "usart3_dev3"   
 | 
					            default "usart3_dev3"   
 | 
				
			||||||
    endif
 | 
					    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
 | 
					menuconfig BSP_USING_UART6
 | 
				
			||||||
    bool "Enable USART6"
 | 
					    bool "Enable USART6"
 | 
				
			||||||
    default n
 | 
					    default n
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,14 @@ Modification:
 | 
				
			||||||
#define USART3_TX_PIN                   (GPIO_PIN_10)
 | 
					#define USART3_TX_PIN                   (GPIO_PIN_10)
 | 
				
			||||||
#endif
 | 
					#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)
 | 
					#if defined(BSP_USING_UART6)
 | 
				
			||||||
#define USART6_RX_PORT                  (GPIO_PORT_H)
 | 
					#define USART6_RX_PORT                  (GPIO_PORT_H)
 | 
				
			||||||
#define USART6_RX_PIN                   (GPIO_PIN_06)
 | 
					#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);
 | 
					        GPIO_SetFunc(USART3_TX_PORT, USART3_TX_PIN, GPIO_FUNC_32);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
#endif
 | 
					#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
 | 
					#ifdef BSP_USING_UART6
 | 
				
			||||||
    case (uint32)CM_USART6:
 | 
					    case (uint32)CM_USART6:
 | 
				
			||||||
        GPIO_SetFunc(USART6_RX_PORT, USART6_RX_PIN, GPIO_FUNC_37);
 | 
					        GPIO_SetFunc(USART6_RX_PORT, USART6_RX_PIN, GPIO_FUNC_37);
 | 
				
			||||||
| 
						 | 
					@ -123,6 +137,32 @@ void Uart3RxErrIrqHandler(void)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#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
 | 
					#ifdef BSP_USING_UART6
 | 
				
			||||||
struct SerialBus serial_bus_6;
 | 
					struct SerialBus serial_bus_6;
 | 
				
			||||||
struct SerialDriver serial_driver_6;
 | 
					struct SerialDriver serial_driver_6;
 | 
				
			||||||
| 
						 | 
					@ -499,6 +539,57 @@ int HwUsartInit(void)
 | 
				
			||||||
    }  
 | 
					    }  
 | 
				
			||||||
#endif
 | 
					#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
 | 
					#ifdef BSP_USING_UART6
 | 
				
			||||||
    static struct SerialCfgParam serial_cfg_6;
 | 
					    static struct SerialCfgParam serial_cfg_6;
 | 
				
			||||||
    memset(&serial_cfg_6, 0, sizeof(struct SerialCfgParam));
 | 
					    memset(&serial_cfg_6, 0, sizeof(struct SerialCfgParam));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 */
 | 
				
			||||||
            MdelayKTask(1000);
 | 
					    if (get_udp_test_info()->task_on) {
 | 
				
			||||||
        }
 | 
					        KPrintf("[%s] Waiting former udp send task to exit.\n");
 | 
				
			||||||
        udp_send_num = 1;
 | 
					    }
 | 
				
			||||||
 | 
					    while (get_udp_test_info()->task_on) {
 | 
				
			||||||
 | 
					        MdelayKTask(1000);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t enet_port = 0; ///< test enet port 0
 | 
					    get_udp_test_info()->given_ip = false;
 | 
				
			||||||
    memset(udp_demo_msg, 0, sizeof(udp_demo_msg));
 | 
					    get_udp_test_info()->given_port = false;
 | 
				
			||||||
 | 
					    get_udp_test_info()->given_msg = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(argc == 1) {
 | 
					    /* Parse options */
 | 
				
			||||||
        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);
 | 
					    char* msg_ptr = NULL;
 | 
				
			||||||
        strncpy(udp_demo_msg, hello_str, strlen(hello_str));
 | 
					    char* ip_ptr = NULL;
 | 
				
			||||||
        udp_send_num = 10;
 | 
					    bool is_help = false;
 | 
				
			||||||
        udp_interval = 100;
 | 
					    struct argparse_option options[] = {
 | 
				
			||||||
    } else {
 | 
					        OPT_HELP(&is_help),
 | 
				
			||||||
        strncpy(udp_demo_msg, argv[1], strlen(argv[1]));
 | 
					        OPT_STRING(SEND_MESSAGE, "message", &msg_ptr, "MESSAGE to send", NULL, 0, 0),
 | 
				
			||||||
        strncat(udp_demo_msg, "\r\n", 3);
 | 
					        OPT_STRING(TARGET_IP, "ip", &ip_ptr, "target IP to send upd messages", NULL, 0, 0),
 | 
				
			||||||
        if(argc >= 3) {
 | 
					        OPT_INTEGER(TARGET_PORT, "port", &get_udp_test_info()->port, "target PORT to send udp messages", NULL, 0, 0),
 | 
				
			||||||
            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);
 | 
					        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),
 | 
				
			||||||
        if(argc > 3) {
 | 
					        OPT_END(),
 | 
				
			||||||
            sscanf(argv[3], "%d", &udp_send_num);
 | 
					    };
 | 
				
			||||||
            sscanf(argv[4], "%d", &udp_interval);
 | 
					
 | 
				
			||||||
        }
 | 
					    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;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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);
 | 
					    // translate string to array
 | 
				
			||||||
 | 
					    sscanf(ip_ptr, "%d.%d.%d.%d", &get_udp_test_info()->ip[0], &get_udp_test_info()->ip[1], &get_udp_test_info()->ip[2], &get_udp_test_info()->ip[3]);
 | 
				
			||||||
 | 
					    int msg_len = strlen(msg_ptr);
 | 
				
			||||||
 | 
					    strncpy(udp_demo_buffer, msg_ptr, msg_len < UDP_BUFFER_SIZE ? msg_len : UDP_BUFFER_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //init lwip and net dirver
 | 
					    /* start task */
 | 
				
			||||||
    lwip_config_net(enet_port, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
					    KPrintf("[%s] gw %d.%d.%d.%d:%d send time %d udp_interval %d\n", __func__,
 | 
				
			||||||
 | 
					        get_udp_test_info()->ip[0], get_udp_test_info()->ip[1], get_udp_test_info()->ip[2], get_udp_test_info()->ip[3],
 | 
				
			||||||
 | 
					        get_udp_test_info()->port,
 | 
				
			||||||
 | 
					        get_udp_test_info()->num,
 | 
				
			||||||
 | 
					        get_udp_test_info()->interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lwip_config_net(0, lwip_ipaddr, lwip_netmask, lwip_gwaddr);
 | 
				
			||||||
    sys_thread_new("udp send", LwipUDPSendTask, NULL, LWIP_TASK_STACK_SIZE, LWIP_DEMO_TASK_PRIO);
 | 
					    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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,7 @@ Modification:
 | 
				
			||||||
#include <bus_serial.h>
 | 
					#include <bus_serial.h>
 | 
				
			||||||
#include <dev_serial.h>
 | 
					#include <dev_serial.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int serial_isr_cnt = 0;
 | 
				
			||||||
static DoubleLinklistType serialdev_linklist;
 | 
					static DoubleLinklistType serialdev_linklist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int SerialWorkModeCheck(struct SerialDevParam *serial_dev_param)
 | 
					static int SerialWorkModeCheck(struct SerialDevParam *serial_dev_param)
 | 
				
			||||||
| 
						 | 
					@ -138,6 +139,9 @@ static inline int SerialDevIntRead(struct SerialHardwareDevice *serial_dev, stru
 | 
				
			||||||
        if (serial_dev->serial_fifo.serial_rx->serial_recv_num == serial_dev->serial_fifo.serial_rx->serial_send_num) {
 | 
					        if (serial_dev->serial_fifo.serial_rx->serial_recv_num == serial_dev->serial_fifo.serial_rx->serial_send_num) {
 | 
				
			||||||
            if (RET_FALSE == serial_dev->serial_fifo.serial_rx->serial_rx_full) {
 | 
					            if (RET_FALSE == serial_dev->serial_fifo.serial_rx->serial_rx_full) {
 | 
				
			||||||
                CriticalAreaUnLock(lock);
 | 
					                CriticalAreaUnLock(lock);
 | 
				
			||||||
 | 
					                if (0 == serial_isr_cnt) {
 | 
				
			||||||
 | 
					                    KSemaphoreSetValue(serial_dev->haldev.dev_sem, 0);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -151,11 +155,13 @@ static inline int SerialDevIntRead(struct SerialHardwareDevice *serial_dev, stru
 | 
				
			||||||
        if (RET_TRUE == serial_dev->serial_fifo.serial_rx->serial_rx_full) {
 | 
					        if (RET_TRUE == serial_dev->serial_fifo.serial_rx->serial_rx_full) {
 | 
				
			||||||
            serial_dev->serial_fifo.serial_rx->serial_rx_full = RET_FALSE;
 | 
					            serial_dev->serial_fifo.serial_rx->serial_rx_full = RET_FALSE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (serial_isr_cnt > 0) {
 | 
				
			||||||
 | 
					            serial_isr_cnt--;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CriticalAreaUnLock(lock);
 | 
					        CriticalAreaUnLock(lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //MdelayKTask(20);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        *read_data = get_char;
 | 
					        *read_data = get_char;
 | 
				
			||||||
        read_data++; 
 | 
					        read_data++; 
 | 
				
			||||||
        read_length--;
 | 
					        read_length--;
 | 
				
			||||||
| 
						 | 
					@ -713,6 +719,10 @@ void SerialSetIsr(struct SerialHardwareDevice *serial_dev, int event)
 | 
				
			||||||
                if (serial_dev->haldev.dev_recv_callback) {
 | 
					                if (serial_dev->haldev.dev_recv_callback) {
 | 
				
			||||||
                    serial_dev->haldev.dev_recv_callback((void *)serial_dev, serial_rx_length);
 | 
					                    serial_dev->haldev.dev_recv_callback((void *)serial_dev, serial_rx_length);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                lock = CriticalAreaLock();
 | 
				
			||||||
 | 
					                serial_isr_cnt += 1;
 | 
				
			||||||
 | 
					                CriticalAreaUnLock(lock);
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
                KSemaphoreAbandon(serial_dev->haldev.dev_sem);
 | 
					                KSemaphoreAbandon(serial_dev->haldev.dev_sem);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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